it-swarm.com.ru

Случайная перетасовка массива

Мне нужно случайным образом перемешать следующий массив:

int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};

Есть ли какая-либо функция для этого?

192
Hubert

Использование коллекций для перемешивания массива примитивных типов - это немного излишне ...

Достаточно просто реализовать эту функцию самостоятельно, используя, например, перемешивание Фишера – Йейтса :

import Java.util.*;
import Java.util.concurrent.ThreadLocalRandom;

class Test
{
  public static void main(String args[])
  {
    int[] solutionArray = { 1, 2, 3, 4, 5, 6, 16, 15, 14, 13, 12, 11 };

    shuffleArray(solutionArray);
    for (int i = 0; i < solutionArray.length; i++)
    {
      System.out.print(solutionArray[i] + " ");
    }
    System.out.println();
  }

  // Implementing Fisher–Yates shuffle
  static void shuffleArray(int[] ar)
  {
    // If running on Java 6 or older, use `new Random()` on RHS here
    Random rnd = ThreadLocalRandom.current();
    for (int i = ar.length - 1; i > 0; i--)
    {
      int index = rnd.nextInt(i + 1);
      // Simple swap
      int a = ar[index];
      ar[index] = ar[i];
      ar[i] = a;
    }
  }
}
237
PhiLho

Вот простой способ использования ArrayList:

List<Integer> solution = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
    solution.add(i);
}
Collections.shuffle(solution);
143
methodin

Вот работающая и эффективная функция массива Фишера-Йейтса:

private static void shuffleArray(int[] array)
{
    int index;
    Random random = new Random();
    for (int i = array.length - 1; i > 0; i--)
    {
        index = random.nextInt(i + 1);
        if (index != i)
        {
            array[index] ^= array[i];
            array[i] ^= array[index];
            array[index] ^= array[i];
        }
    }
}

или же

private static void shuffleArray(int[] array)
{
    int index, temp;
    Random random = new Random();
    for (int i = array.length - 1; i > 0; i--)
    {
        index = random.nextInt(i + 1);
        temp = array[index];
        array[index] = array[i];
        array[i] = temp;
    }
}
93
Dan Bray

Коллекции class имеет эффективный метод тасования, который можно скопировать, чтобы не зависеть от него:

/**
 * Usage:
 *    int[] array = {1, 2, 3};
 *    Util.shuffle(array);
 */
public class Util {

    private static Random random;

    /**
     * Code from method Java.util.Collections.shuffle();
     */
    public static void shuffle(int[] array) {
        if (random == null) random = new Random();
        int count = array.length;
        for (int i = count; i > 1; i--) {
            swap(array, i - 1, random.nextInt(i));
        }
    }

    private static void swap(int[] array, int i, int j) {
        int temp = array[i];
        array[i] = array[j];
        array[j] = temp;
    }
}
22
KitKat

Посмотрите на класс Collections , в частности, shuffle(...).

12
Dave

У вас есть несколько вариантов здесь. Список немного отличается от массива, когда дело доходит до перемешивания.

Как вы можете видеть ниже, массив быстрее, чем список, а примитивный массив быстрее, чем массив объектов.

Длительность образца

List<Integer> Shuffle: 43133ns
    Integer[] Shuffle: 31884ns
        int[] Shuffle: 25377ns

Ниже представлены три различных варианта воспроизведения в случайном порядке. Вы должны использовать Collections.shuffle, только если вы имеете дело с коллекцией. Нет необходимости заключать ваш массив в коллекцию только для его сортировки. Приведенные ниже методы очень просты в реализации.

ShuffleUtil Class

import Java.lang.reflect.Array;
import Java.util.*;

public class ShuffleUtil<T> {
    private static final int[] EMPTY_INT_ARRAY = new int[0];
    private static final int SHUFFLE_THRESHOLD = 5;

    private static Random Rand;

Основной метод

    public static void main(String[] args) {
        List<Integer> list = null;
        Integer[] arr = null;
        int[] iarr = null;

        long start = 0;
        int cycles = 1000;
        int n = 1000;

        // Shuffle List<Integer>
        start = System.nanoTime();
        list = range(n);
        for (int i = 0; i < cycles; i++) {
            ShuffleUtil.shuffle(list);
        }
        System.out.printf("%22s: %dns%n", "List<Integer> Shuffle", (System.nanoTime() - start) / cycles);

        // Shuffle Integer[]
        start = System.nanoTime();
        arr = toArray(list);
        for (int i = 0; i < cycles; i++) {
            ShuffleUtil.shuffle(arr);
        }
        System.out.printf("%22s: %dns%n", "Integer[] Shuffle", (System.nanoTime() - start) / cycles);

        // Shuffle int[]
        start = System.nanoTime();
        iarr = toPrimitive(arr);
        for (int i = 0; i < cycles; i++) {
            ShuffleUtil.shuffle(iarr);
        }
        System.out.printf("%22s: %dns%n", "int[] Shuffle", (System.nanoTime() - start) / cycles);
    }

Перемешивание общего списка

    // ================================================================
    // Shuffle List<T> (Java.lang.Collections)
    // ================================================================
    @SuppressWarnings("unchecked")
    public static <T> void shuffle(List<T> list) {
        if (Rand == null) {
            Rand = new Random();
        }
        int size = list.size();
        if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
            for (int i = size; i > 1; i--) {
                swap(list, i - 1, Rand.nextInt(i));
            }
        } else {
            Object arr[] = list.toArray();

            for (int i = size; i > 1; i--) {
                swap(arr, i - 1, Rand.nextInt(i));
            }

            ListIterator<T> it = list.listIterator();
            int i = 0;

            while (it.hasNext()) {
                it.next();
                it.set((T) arr[i++]);
            }
        }
    }

    public static <T> void swap(List<T> list, int i, int j) {
        final List<T> l = list;
        l.set(i, l.set(j, l.get(i)));
    }

    public static <T> List<T> shuffled(List<T> list) {
        List<T> copy = copyList(list);
        shuffle(copy);
        return copy;
    }

Перестановка универсального массива

    // ================================================================
    // Shuffle T[]
    // ================================================================
    public static <T> void shuffle(T[] arr) {
        if (Rand == null) {
            Rand = new Random();
        }

        for (int i = arr.length - 1; i > 0; i--) {
            swap(arr, i, Rand.nextInt(i + 1));
        }
    }

    public static <T> void swap(T[] arr, int i, int j) {
        T tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    public static <T> T[] shuffled(T[] arr) {
        T[] copy = Arrays.copyOf(arr, arr.length);
        shuffle(copy);
        return copy;
    }

Перетасовка примитивного массива

    // ================================================================
    // Shuffle int[]
    // ================================================================
    public static <T> void shuffle(int[] arr) {
        if (Rand == null) {
            Rand = new Random();
        }

        for (int i = arr.length - 1; i > 0; i--) {
            swap(arr, i, Rand.nextInt(i + 1));
        }
    }

    public static <T> void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    public static int[] shuffled(int[] arr) {
        int[] copy = Arrays.copyOf(arr, arr.length);
        shuffle(copy);
        return copy;
    }

Полезные методы

Простые служебные методы для копирования и преобразования массивов в списки и наоборот.

    // ================================================================
    // Utility methods
    // ================================================================
    protected static <T> List<T> copyList(List<T> list) {
        List<T> copy = new ArrayList<T>(list.size());
        for (T item : list) {
            copy.add(item);
        }
        return copy;
    }

    protected static int[] toPrimitive(Integer[] array) {
        if (array == null) {
            return null;
        } else if (array.length == 0) {
            return EMPTY_INT_ARRAY;
        }
        final int[] result = new int[array.length];
        for (int i = 0; i < array.length; i++) {
            result[i] = array[i].intValue();
        }
        return result;
    }

    protected static Integer[] toArray(List<Integer> list) {
        return toArray(list, Integer.class);
    }

    protected static <T> T[] toArray(List<T> list, Class<T> clazz) {
        @SuppressWarnings("unchecked")
        final T[] arr = list.toArray((T[]) Array.newInstance(clazz, list.size()));
        return arr;
    }

Класс Range

Создает диапазон значений, аналогичный функции Python range.

    // ================================================================
    // Range class for generating a range of values.
    // ================================================================
    protected static List<Integer> range(int n) {
        return toList(new Range(n), new ArrayList<Integer>());
    }

    protected static <T> List<T> toList(Iterable<T> iterable) {
        return toList(iterable, new ArrayList<T>());
    }

    protected static <T> List<T> toList(Iterable<T> iterable, List<T> destination) {
        addAll(destination, iterable.iterator());

        return destination;
    }

    protected static <T> void addAll(Collection<T> collection, Iterator<T> iterator) {
        while (iterator.hasNext()) {
            collection.add(iterator.next());
        }
    }

    private static class Range implements Iterable<Integer> {
        private int start;
        private int stop;
        private int step;

        private Range(int n) {
            this(0, n, 1);
        }

        private Range(int start, int stop) {
            this(start, stop, 1);
        }

        private Range(int start, int stop, int step) {
            this.start = start;
            this.stop = stop;
            this.step = step;
        }

        @Override
        public Iterator<Integer> iterator() {
            final int min = start;
            final int max = stop / step;

            return new Iterator<Integer>() {
                private int current = min;

                @Override
                public boolean hasNext() {
                    return current < max;
                }

                @Override
                public Integer next() {
                    if (hasNext()) {
                        return current++ * step;
                    } else {
                        throw new NoSuchElementException("Range reached the end");
                    }
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException("Can't remove values from a Range");
                }
            };
        }
    }
}
9
Mr. Polywhirl

Вот полное решение с использованием подхода Collections.shuffle:

public static void shuffleArray(int[] array) {
  List<Integer> list = new ArrayList<>();
  for (int i : array) {
    list.add(i);
  }

  Collections.shuffle(list);

  for (int i = 0; i < list.size(); i++) {
    array[i] = list.get(i);
  }    
}

Обратите внимание, что он страдает из-за неспособности Java плавно переводить между int[] и Integer[] (и, следовательно, int[] и List<Integer>).

9
Duncan Jones

Использование ArrayList<Integer> может помочь вам решить проблему перетасовки, не применяя много логики и не тратя меньше времени. Вот что я предлагаю:

ArrayList<Integer> x = new ArrayList<Integer>();
for(int i=1; i<=add.length(); i++)
{
    x.add(i);
}
Collections.shuffle(x);
8
SalmaanKhan

Следующий код достигнет случайного порядка в массиве. 

// Shuffle the elements in the array
Collections.shuffle(Arrays.asList(array));

от: http://www.programcreek.com/2012/02/Java-method-to-shuffle-an-int-array-with-random-order/

6
Rajib Biswas

Вы можете использовать Java 8 сейчас:

Collections.addAll(list, arr);
Collections.shuffle(list);
cardsList.toArray(arr);
4

Вот универсальная версия для массивов:

import Java.util.Random;

public class Shuffle<T> {

    private final Random rnd;

    public Shuffle() {
        rnd = new Random();
    }

    /**
     * Fisher–Yates shuffle.
     */
    public void shuffle(T[] ar) {
        for (int i = ar.length - 1; i > 0; i--) {
            int index = rnd.nextInt(i + 1);
            T a = ar[index];
            ar[index] = ar[i];
            ar[i] = a;
        }
    }
}

Учитывая, что ArrayList - это просто массив, может быть целесообразно работать с ArrayList вместо явного массива и использовать Collections.shuffle (). Тесты производительности, однако, не показывают какой-либо существенной разницы между приведенным выше и Collections.sort ():

Shuffe<Integer>.shuffle(...) performance: 576084 shuffles per second
Collections.shuffle(ArrayList<Integer>) performance: 629400 shuffles per second
MathArrays.shuffle(int[]) performance: 53062 shuffles per second

Реализация Apache Commons MathArrays.shuffle ограничена int [], и снижение производительности, вероятно, связано с использованием генератора случайных чисел.

3
user1050755

Вот решение с использованием Apache Commons Math 3.x (только для массивов int []):

MathArrays.shuffle(array);

http://commons.Apache.org/proper/commons-math/javadocs/api-3.6.1/org/Apache/commons/math3/util/MathArrays.html#shuffle (int [])

В качестве альтернативы Apache Commons Lang 3.6 представил новые методы shuffle для класса ArrayUtils (для объектов и любого примитивного типа).

ArrayUtils.shuffle(array);

http://commons.Apache.org/proper/commons-lang/javadocs/api-release/org/Apache/commons/lang3/ArrayUtils.html#shuffle-int:A-

3
Emmanuel Bourg
Random rnd = new Random();
for (int i = ar.length - 1; i > 0; i--)
{
  int index = rnd.nextInt(i + 1);
  // Simple swap
  int a = ar[index];
  ar[index] = ar[i];
  ar[i] = a;
}

Кстати, я заметил, что этот код возвращает ar.length - 1 количество элементов, поэтому, если ваш массив имеет 5 элементов, новый перемешанный массив будет иметь 4 элемента. Это происходит потому, что цикл for говорит i>0. Если вы измените на i>=0, вы получите все элементы перемешанными.

3
Cristiane Dos Santos Costa

В некоторых ответах я увидел информацию о пропусках, поэтому решил добавить новую.

Коллекции Java Arrays.asList принимает var-arg типа T (T ...). Если вы передадите массив примитивов (массив int), метод asList выведет и сгенерирует List<int[]>, который является списком из одного элемента (один элемент является массивом примитивов). если вы перетасуете этот список из одного элемента, он ничего не изменит.

Итак, сначала вы должны преобразовать свой примитивный массив в массив объектов Wrapper. для этого вы можете использовать метод ArrayUtils.toObject из Apache.commons.lang. затем передайте сгенерированный массив в List и, наконец, перемешайте его.

  int[] intArr = {1,2,3};
  List<Integer> integerList = Arrays.asList(ArrayUtils.toObject(array));
  Collections.shuffle(integerList);
  //now! elements in integerList are shuffled!
3
Mr.Q
  1. Поле от int[] до Integer[]
  2. Обтекание массив в список с помощью метода Arrays.asList
  3. Перемешать с методом Collections.shuffle

    int[] solutionArray = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1 };
    
    Integer[] boxed = Arrays.stream(solutionArray).boxed().toArray(Integer[]::new);
    Collections.shuffle(Arrays.asList(boxed));
    
    System.out.println(Arrays.toString(boxed));
    // [1, 5, 5, 4, 2, 6, 1, 3, 3, 4, 2, 6]
    
2
YujiSoftware

Вот еще один способ перемешать список

public List<Integer> shuffleArray(List<Integer> a) {
List<Integer> b = new ArrayList<Integer>();
    while (a.size() != 0) {
        int arrayIndex = (int) (Math.random() * (a.size()));
        b.add(a.get(arrayIndex));
        a.remove(a.get(arrayIndex));
    }
    return b;
}

Выберите случайное число из исходного списка и сохраните его в другом списке. Затем удалите число из исходного списка. Размер исходного списка будет уменьшаться на единицу, пока все элементы не будут перемещены в новый список. 

2
PS5

Простое решение для Groovy:

solutionArray.sort{ new Random().nextInt() }

Это позволит отсортировать все элементы списка массивов случайным образом, что приведет к архивированию желаемого результата перемешивания всех элементов.

1
Hans Kristian

Самое простое решение для этой случайной перестановки в массиве.

String location[] = {"delhi","banglore","mathura","lucknow","chandigarh","mumbai"};
int index;
String temp;
Random random = new Random();
for(int i=1;i<location.length;i++)
{
    index = random.nextInt(i+1);
    temp = location[index];
    location[index] = location[i];
    location[i] = temp;
    System.out.println("Location Based On Random Values :"+location[i]);
}
1
Archit Goel

Простейший код для перемешивания:

import Java.util.*;
public class ch {
    public static void main(String args[])
    {
        Scanner sc=new Scanner(System.in);
        ArrayList<Integer> l=new ArrayList<Integer>(10);
        for(int i=0;i<10;i++)
            l.add(sc.nextInt());
        Collections.shuffle(l);
        for(int j=0;j<10;j++)
            System.out.println(l.get(j));       
    }
}
1
suraj

Я взвешиваю этот очень популярный вопрос, потому что никто не написал версию в случайном порядке. Стиль заимствован из Arrays.Java, потому что кто не грабит технологию Java в наши дни? Общие и int реализации включены.

   /**
    * Shuffles elements from {@code original} into a newly created array.
    *
    * @param original the original array
    * @return the new, shuffled array
    * @throws NullPointerException if {@code original == null}
    */
   @SuppressWarnings("unchecked")
   public static <T> T[] shuffledCopy(T[] original) {
      int originalLength = original.length; // For exception priority compatibility.
      Random random = new Random();
      T[] result = (T[]) Array.newInstance(original.getClass().getComponentType(), originalLength);

      for (int i = 0; i < originalLength; i++) {
         int j = random.nextInt(i+1);
         result[i] = result[j];
         result[j] = original[i];
      }

      return result;
   }


   /**
    * Shuffles elements from {@code original} into a newly created array.
    *
    * @param original the original array
    * @return the new, shuffled array
    * @throws NullPointerException if {@code original == null}
    */
   public static int[] shuffledCopy(int[] original) {
      int originalLength = original.length;
      Random random = new Random();
      int[] result = new int[originalLength];

      for (int i = 0; i < originalLength; i++) {
         int j = random.nextInt(i+1);
         result[i] = result[j];
         result[j] = original[i];
      }

      return result;
   }
1
QED

Есть и другой способ, еще не пост

//that way, send many object types diferentes
public anotherWayToReciveParameter(Object... objects)
{
    //ready with array
    final int length =objects.length;
    System.out.println(length);
    //for ready same list
    Arrays.asList(objects);
}

так проще, зависит от контекста

1
Marcelo Ferreira

Это алгоритм Knuth Shuffle.

public class Knuth { 

    // this class should not be instantiated
    private Knuth() { }

    /**
     * Rearranges an array of objects in uniformly random order
     * (under the assumption that <tt>Math.random()</tt> generates independent
     * and uniformly distributed numbers between 0 and 1).
     * @param a the array to be shuffled
     */
    public static void shuffle(Object[] a) {
        int n = a.length;
        for (int i = 0; i < n; i++) {
            // choose index uniformly in [i, n-1]
            int r = i + (int) (Math.random() * (n - i));
            Object swap = a[r];
            a[r] = a[i];
            a[i] = swap;
        }
    }

    /**
     * Reads in a sequence of strings from standard input, shuffles
     * them, and prints out the results.
     */
    public static void main(String[] args) {

        // read in the data
        String[] a = StdIn.readAllStrings();

        // shuffle the array
        Knuth.shuffle(a);

        // print results.
        for (int i = 0; i < a.length; i++)
            StdOut.println(a[i]);
    }
}
1
BufBills

Одним из решений является использование перестановки для предварительного вычисления всех перестановок и сохранения в ArrayList

Java 8 представила новый метод, ints (), в классе Java.util.Random. Метод ints () возвращает неограниченный поток псевдослучайных значений int. Вы можете ограничить случайные числа между указанным диапазоном, указав минимальное и максимальное значения.

Random genRandom = new Random();
int num = genRandom.nextInt(arr.length);

С помощью генерации случайного числа, вы можете перебрать цикл и поменять местами текущий индекс со случайным числом .. Вот так вы можете сгенерировать случайное число с O(1) сложностью пространства.

0
Maulik Sakhida

Используя Guava Ints.asList() это так просто, как:

Collections.shuffle(Ints.asList(array));
0
BeeOnRope
public class ShuffleArray {
public static void shuffleArray(int[] a) {
    int n = a.length;
    Random random = new Random();
    random.nextInt();
    for (int i = 0; i < n; i++) {
        int change = i + random.nextInt(n - i);
        swap(a, i, change);
    }
}

private static void swap(int[] a, int i, int change) {
    int helper = a[i];
    a[i] = a[change];
    a[change] = helper;
}

public static void main(String[] args) {
    int[] a = new int[] { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1 };
    shuffleArray(a);
    for (int i : a) {
        System.out.println(i);
    }
}
}
0
nikhil gupta

похоже без использования свопа б

        Random r = new Random();
    int n = solutionArray.length;
    List<Integer> arr =  Arrays.stream(solutionArray).boxed().collect(Collectors.toList());
    for (int i = 0; i < n-1; i++) {
        solutionArray[i] = arr.remove( r.nextInt(arr.size())); // randomize base on size
    }
    solutionArray[n-1] = arr.get(0);
0
digitebs
import Java.util.ArrayList;
import Java.util.Random;
public class shuffle {
    public static void main(String[] args) {
        int a[] =  {1,2,3,4,5,6,7,8,9};
         ArrayList b = new ArrayList();
       int i=0,q=0;
       Random Rand = new Random();

       while(a.length!=b.size())
       {
           int l = Rand.nextInt(a.length);
//this is one option to that but has a flaw on 0
//           if(a[l] !=0)
//           {
//                b.add(a[l]);
//               a[l]=0;
//               
//           }
//           
// this works for every no. 
                if(!(b.contains(a[l])))
                {
                    b.add(a[l]);
                }



       }

//        for (int j = 0; j <b.size(); j++) {
//            System.out.println(b.get(j));
//            
//        }
System.out.println(b);
    }

}
0
aurobind singh