【问题标题】:Random shuffling of an array数组的随机洗牌
【发布时间】:2010-12-03 22:24:21
【问题描述】:

我需要随机打乱以下数组:

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

有什么功能可以做到吗?

【问题讨论】:

  • 这是你要找的SDK方法 Collections.shuffle(Arrays.asList(array));
  • @Louie 不,这行不通。这将创建一个包含一个条目的List<int[]>。有关使用Collections.shuffle() 实现此目的的方法,请参阅my answer
  • 不是原始问题的真正答案,但来自 commons-math3 库的 MathArrays.shuffle 可以完成这项工作。
  • 这不足以保证答案的主题,但我记得“图形宝石”一书中的一篇非常酷的文章,它谈到了以伪随机顺序遍历数组。在我看来,这胜过一开始就必须对数据进行真正的洗牌。 C 实现在这里找到github.com/erich666/GraphicsGems/blob/master/gems/Dissolve.c
  • 另见这个密切相关的问题:stackoverflow.com/questions/2450954/…

标签: java arrays random shuffle


【解决方案1】:

查看Collections 类,特别是shuffle(...)

【讨论】:

  • 你如何在 Android 中使用这个 Collections 类?你需要做一个特殊的导入(CRTL SHIFT O 不起作用)才能使用它?
  • @Hubert 它应该是包java.util 的一部分。从 v1.2 开始,它就是标准库的一部分。
  • 为了让您的答案更加独立,它应该包含示例代码。即:import java.util.Collections; shuffle(solutionArray);
【解决方案2】:

使用集合来洗牌一个原始类型数组有点过头了......

自己实现该功能很简单,例如使用Fisher–Yates shuffle

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;
    }
  }
}

【讨论】:

  • 最好使用 Collections.shuffle(Arrays.asList(array));然后自己洗牌。
  • @Louie Collections.shuffle(Arrays.asList(array)) 不起作用,因为 Arrays.asList(array) 返回 Collection&lt;int[]&gt; 而不是您想象的 Collection&lt;Integer&gt;
  • @exhuma 因为如果您有一个包含数千或数百万个原始值的数组要排序,那么将每个原始值包装在一个对象中只是为了进行排序在内存和 CPU 中都有点开销。
  • 不是费雪-耶茨洗牌。这称为Durstenfeld shuffle。原始的 Fisher-yates shuffle 运行时间为 O(n^2),非常慢。
  • @ShoeLace1291 如果我没记错的话,你不能在 Java 中使用:没有办法让方法可以通用地处理原语(int)和对象(字符串)。你必须复制它。
【解决方案3】:

这是使用ArrayList 的简单方法:

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

【讨论】:

  • 你可以直接Collectons.shuffle(Arrays.asList(solutionArray));
  • @Timmos 你错了。 Arrays.asList 环绕原始数组,因此修改它会修改原始数组。这就是你不能添加或删除的原因,因为数组是固定大小的。
  • @Nand 不确定我在想什么,但查看源代码,确实 Arrays.asList 方法创建了一个由给定数组支持的 ArrayList。感谢您指出。删除了我之前的评论(无法编辑)。
【解决方案4】:

这是一个有效的 Fisher-Yates 洗牌数组函数:

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;
    }
}

【讨论】:

  • 投了赞成票,因为我需要一个没有创建整数集合的高开销的解决方案
  • 第二种实现不是有可能与自己的索引交换吗? random.nextInt(int bound) 是独占的,但将其 i + 1 作为参数将允许 indexi 可能相同。
  • @bmcentee148 以随机顺序交换元素是允许的。不理解这一点会削弱 Enigma 并帮助 Alan Turing 破解它。 en.wikipedia.org/wiki/…
  • xor 技巧非常适合在 CPU 没有交换指令且没有空闲寄存器时交换 CPU 寄存器,但对于在循环内交换数组元素,我看不到任何好处。对于临时局部变量,没有理由在循环外声明它们。
  • 在循环外声明temp 变量会稍微高效一些。 XOR 技巧应该比使用 temp 变量更快,但这是确保它执行基准测试的唯一方法。
【解决方案5】:

Collections类有一个高效的洗牌方法,可以复制,以免依赖:

/**
 * 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;
    }
}

【讨论】:

  • 以免依赖它?如果可能的话,我更愿意依赖它。
  • @shmosel 然后随意使用它。确保您导入了所需的类,并且您已将数组转换为带有Arrays.asList 的列表。您也必须将结果列表转换为数组
  • 您不能在原始数组上使用Arrays.asList()。而且您不需要将其转换回来,因为它只是一个包装器。
【解决方案6】:

使用ArrayList&lt;Integer&gt; 可以帮助您解决洗牌问题,而无需应用太多逻辑并花费更少的时间。这是我的建议:

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

【讨论】:

  • 可能不是后者 - 耗时更少。事实上,这肯定比上面的原始实现要慢。
  • 有人复制代码,看“for循环” i=1 也许你需要i=0
【解决方案7】:

这是使用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&lt;Integer&gt;)之间平滑转换,它会受到影响。

【讨论】:

    【解决方案8】:

    这是一个用于数组的泛型版本:

    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[],性能损失可能是由于使用了随机数生成器。

    【讨论】:

    • 看来您可以将new JDKRandomGenerator() 传递给MathArrays.shuffle。我想知道这对性能有何影响?
    • 实际上...看起来MathArrays#shuffle 在其核心循环中有一个分配:int targetIdx = new UniformIntegerDistribution(rng, start, i).sample();。奇怪。
    【解决方案9】:
    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&gt;0。如果更改为i&gt;=0,所有元素都会被打乱。

    【讨论】:

    • 请注意,您可能希望将其移至问题的评论部分,因为如果将其作为自己的答案,它可能会被标记。
    • 这似乎回答了这个问题,所以我不确定你在说什么@JasonD
    • 代码正确,注释错误。如果将i&gt;0 更改为i&gt;=0,则将0 元素与自身交换会浪费时间。
    【解决方案10】:

    这里有几个选项。在洗牌方面,列表与数组有点不同。

    如下所示,数组比列表快,原始数组比对象数组快。

    示例持续时间

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

    下面是随机播放的三种不同实现。如果你正在处理一个集合,你应该只使用 Collections.shuffle。无需将数组包装到集合中即可对其进行排序。下面的方法很容易实现。

    ShuffleUtil 类

    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;
        }
    

    范围类

    生成一系列值,类似于 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");
                    }
                };
            }
        }
    }
    

    【讨论】:

    • 你没有为相同的事情计时,你只为每个事情计时一次(然后他们的订单很重要,你忘记了运行时优化)。您应该在任何计时之前调用rangetoArraytoPrimitive,并循环以能够得出任何结论(伪代码:执行几次{ 生成列表、arr 和 iarr;时间洗牌列表;时间洗牌 arr;时间改组 iarr })。我的结果:第一:list: 36017ns, arr: 28262ns, iarr: 23334ns。第 100 位:list: 18445ns, arr: 19995ns, iarr: 18657ns。它只是显示 int[] 已预先优化(通过代码),但它们几乎等同于运行时优化。
    【解决方案11】:

    您现在可以使用 java 8:

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

    【讨论】:

    • 这段代码中没有 Java8 特定的内容。这从 Java2 开始有效。好吧,一旦你解决了第一次使用list 和突然引用cardsList 之间的不一致,它就会起作用。但是由于您需要创建临时的list,而您已经省略了它,因此这里多次显示的Collections.shuffle(Arrays.asList(arr)); 方法没有任何好处。这也适用于 Java2。
    【解决方案12】:

    我正在考虑这个非常受欢迎的问题,因为没有人编写过随机复制版本。风格从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;
       }
    

    【讨论】:

      【解决方案13】:

      以下代码将实现对数组的随机排序。

      // 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/

      【讨论】:

      • 请注意它不适用于原始数组,因为 Arrays.asList 将原始数组视为一个元素
      • 如果数组包含许多对象而不是通常的原始数组呢?
      【解决方案14】:

      这是 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]);
          }
      }
      

      【讨论】:

        【解决方案15】:

        这是使用 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 为 ArrayUtils 类(用于对象和任何原始类型)引入了新的随机播放方法。

        ArrayUtils.shuffle(array);
        

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

        【讨论】:

          【解决方案16】:

          还有另一种方式,还没发帖

          //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);
          }
          

          这样更容易,取决于上下文

          【讨论】:

            【解决方案17】:

            这种在数组中随机洗牌的最简单的解决方案。

            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]);
            }
            

            【讨论】:

              【解决方案18】:

              我在一些答案中看到了一些遗漏信息,所以我决定添加一个新的。

              Java 集合 Arrays.asList 采用 T (T ...) 类型的 var-arg。如果传递一个原始数组(int 数组),asList 方法将推断并生成一个List&lt;int[]&gt;,这是一个单元素列表(单元素是原始数组)。如果你打乱这个元素列表,它不会改变任何东西。

              因此,首先您必须将原始数组转换为 Wrapper 对象数组。为此,您可以使用 apache.commons.lang 中的 ArrayUtils.toObject 方法。然后将生成的数组传递给 List 并最终随机播放。

                int[] intArr = {1,2,3};
                List<Integer> integerList = Arrays.asList(ArrayUtils.toObject(array));
                Collections.shuffle(integerList);
                //now! elements in integerList are shuffled!
              

              【讨论】:

                【解决方案19】:
                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);
                    }
                }
                }
                

                【讨论】:

                • 请添加一些与您的答案相关的描述。
                【解决方案20】:

                Groovy 的简单解决方案:

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

                这将对数组列表中的所有元素进行随机排序,从而归档所有元素的混洗结果。

                【讨论】:

                  【解决方案21】:
                  1. int[]List&lt;Integer&gt;
                  2. 使用Collections.shuffle 方法随机播放
                  int[] solutionArray = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1 };
                  
                  List<Integer> list = Arrays.stream(solutionArray).boxed().collect(Collectors.toList());
                  Collections.shuffle(list);
                  
                  System.out.println(list.toString());
                  // [1, 5, 5, 4, 2, 6, 1, 3, 3, 4, 2, 6]
                  

                  【讨论】:

                    【解决方案22】:

                    这是另一种随机播放列表的方法

                    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;
                    }
                    

                    从原始列表中选择一个随机数并将其保存在另一个列表中。然后从原始列表中删除该数字。原始列表的大小将不断减一,直到所有元素都移动到新列表中。

                    【讨论】:

                      【解决方案23】:

                      最简单的洗牌代码:

                      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));       
                          }
                      }
                      

                      【讨论】:

                        【解决方案24】:
                        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);
                            }
                        
                        }
                        

                        【讨论】:

                          【解决方案25】:

                          类似但不使用swap b

                              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 based on size
                              }
                              solutionArray[n-1] = arr.get(0);
                          

                          【讨论】:

                            【解决方案26】:

                            其中一种解决方案是使用排列来预先计算所有排列并存储在 ArrayList 中

                            Java 8 在 java.util.Random 类中引入了一个新方法 ints()。 ints() 方法返回无限的伪随机 int 值流。您可以通过提供最小值和最大值来限制指定范围内的随机数。

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

                            在生成随机数的帮助下,您可以遍历循环并将当前索引与随机数交换.. 这样就可以生成具有 O(1) 空间复杂度的随机数。

                            【讨论】:

                              【解决方案27】:

                              使用 Guava 的 Ints.asList() 就这么简单:

                              Collections.shuffle(Ints.asList(array));
                              

                              【讨论】:

                                【解决方案28】:

                                没有随机解:

                                   static void randomArrTimest(int[] some){
                                        long startTime = System.currentTimeMillis();
                                        for (int i = 0; i < some.length; i++) {
                                            long indexToSwap = startTime%(i+1);
                                            long tmp = some[(int) indexToSwap];
                                            some[(int) indexToSwap] = some[i];
                                            some[i] = (int) tmp;
                                        }
                                        System.out.println(Arrays.toString(some));
                                    }
                                

                                【讨论】:

                                  【解决方案29】:

                                  使用随机类

                                    public static void randomizeArray(int[] arr) {
                                  
                                        Random rGenerator = new Random(); // Create an instance of the random class 
                                        for (int i =0; i< arr.length;i++ ) {
                                            //Swap the positions...
                                  
                                            int rPosition = rGenerator.nextInt(arr.length); // Generates an integer within the range (Any number from 0 - arr.length)
                                            int temp = arr[i]; // variable temp saves the value of the current array index;
                                            arr[i] = arr[rPosition];  // array at the current position (i) get the value of the random generated 
                                            arr[rPosition] = temp; // the array at the position of random generated gets the value of temp
                                  
                                        }
                                  
                                        for(int i = 0; i<arr.length; i++) {
                                            System.out.print(arr[i]); //Prints out the array
                                        } 
                                  
                                    }
                                  

                                  【讨论】:

                                    【解决方案30】:

                                    您应该使用Collections.shuffle()。但是,您不能直接操作原始类型数组,因此您需要创建一个包装类。

                                    试试这个。

                                    public static void shuffle(int[] array) {
                                        Collections.shuffle(new AbstractList<Integer>() {
                                            @Override public Integer get(int index) { return array[index]; }
                                            @Override public int size() { return array.length; }
                                            @Override public Integer set(int index, Integer element) {
                                                int result = array[index];
                                                array[index] = element;
                                                return result;
                                            }
                                        });
                                    }
                                    

                                    int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};
                                    shuffle(solutionArray);
                                    System.out.println(Arrays.toString(solutionArray));
                                    

                                    输出:

                                    [3, 3, 4, 1, 6, 2, 2, 1, 5, 6, 5, 4]
                                    

                                    【讨论】:

                                      猜你喜欢
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 1970-01-01
                                      • 2011-05-05
                                      • 2015-01-03
                                      • 2015-10-30
                                      • 2016-04-26
                                      相关资源
                                      最近更新 更多