Xáo trộn ngẫu nhiên của một mảng


232

Tôi cần xáo trộn ngẫu nhiên Mảng sau:

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

Có bất kỳ chức năng để làm điều đó?


5
Đây là phương thức SDK mà bạn đang tìm kiếm Collections.shuffle (Arrays.asList (mảng));
Louis Hong

2
@Louie Không, điều đó không hiệu quả. Điều đó sẽ tạo ra một mục List<int[]>chứa. Xem câu trả lời của tôi cho cách để đạt được điều này bằng cách sử dụng Collections.shuffle().
Duncan Jones

2
Không thực sự là một câu trả lời cho câu hỏi ban đầu, nhưng MathArrays.shuffle từ thư viện commons-math3 thực hiện công việc.
Sandris

1
Đây không phải là chủ đề đủ để đảm bảo một câu trả lời, nhưng tôi nhớ một bài viết thực sự hay từ cuốn sách "Đồ họa đá quý" nói về việc vượt qua một mảng theo thứ tự ngẫu nhiên giả. Trong tâm trí của tôi rằng nhịp đập phải thực sự xáo trộn dữ liệu ở nơi đầu tiên. Việc triển khai C được tìm thấy ở đây github.com/erich666/GraphicsGems/blob/master/gems/Dissolve.c
Lennart Rolland

Ngoài ra, hãy xem câu hỏi liên quan chặt chẽ này: stackoverflow.com/questions/2450954/ từ
Pierz

Câu trả lời:


263

Sử dụng Bộ sưu tập để xáo trộn một loạt các kiểu nguyên thủy là một chút quá mức ...

Nó đủ đơn giản để tự thực hiện chức năng, ví dụ như sử dụng shuffle Fisher .

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

26
Nitpick cực kỳ tầm thường, nhưng bạn chỉ có thể sử dụng println()thay vì println(""). Tôi nghĩ rõ ràng hơn trong ý định :)
Cowan

55
Sẽ tốt hơn nhiều khi sử dụng Collections.shuffle (Arrays.asList (mảng)); sau đó thực hiện một shuffle tự của bạn.
Louis Hong

21
@Louie Collections.shuffle(Arrays.asList(array))không hoạt động, vì Arrays.asList(array)trả lại Collection<int[]>không Collection<Integer>như bạn nghĩ.
Adam Stelmaszchot

15
@exhuma Bởi vì nếu bạn có một mảng gồm hàng ngàn hoặc hàng triệu giá trị nguyên thủy để sắp xếp, việc bọc từng đối tượng trong một đối tượng chỉ để thực hiện một sắp xếp sẽ hơi tốn kém, cả về bộ nhớ và CPU.
PhiLho

14
Đây không phải là shuffle Fisher-Yates. Điều này được gọi là xáo trộn Durstenfeld . Việc xáo trộn câu cá ban đầu chạy trong thời gian O (n ^ 2) cực kỳ chậm.
Pacerier

164

Đây là một cách đơn giản bằng cách sử dụng ArrayList:

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

1
Bạn có thể chỉ đơn giảnCollectons.shuffle(Arrays.asList(solutionArray));
FindOutIslamNow

@Timmos Bạn sai rồi. Arrays.asList bao bọc xung quanh mảng ban đầu và do đó sửa đổi nó sửa đổi mảng ban đầu. Đó là lý do tại sao bạn không thể thêm hoặc xóa, vì các mảng có kích thước cố định.
Nand

@ Không chắc chắn những gì tôi đã nghĩ, nhưng nhìn vào mã nguồn, thực sự phương thức Arrays.asList tạo ra một ArrayList được hỗ trợ bởi mảng đã cho. Cảm ơn đã chỉ ra điều đó. Đã xóa nhận xét trước đó của tôi (không thể chỉnh sửa nó).
Timmos

100

Dưới đây là chức năng mảng trộn ngẫu nhiên của Fisher bổ sung 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];
        }
    }
}

hoặc là

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

1
Bỏ phiếu vì tôi cần một giải pháp không có chi phí cao để tạo Bộ sưu tập Số nguyên
mwk

2
Không thực hiện thứ hai có tiềm năng để trao đổi với chỉ mục riêng của mình? random.nextInt(int bound)là độc quyền nhưng đưa ra nó i + 1như là một đối số sẽ cho phép indexicó khả năng giống nhau.
bmcentee148

21
@ bmcentee148 Hoán đổi một phần tử với chính nó được cho phép theo thứ tự ngẫu nhiên. Không hiểu điều này làm suy yếu Enigma và giúp cho Alan Turing bẻ khóa nó. vi.wikipedia.org/wiki/ từ
Ellen Spertus

4
Thủ xorthuật này rất hữu ích cho việc hoán đổi các thanh ghi CPU khi CPU không có lệnh hoán đổi và không có các thanh ghi miễn phí, nhưng để hoán đổi các phần tử mảng trong một vòng lặp, tôi không thấy bất kỳ lợi ích nào. Đối với các biến cục bộ tạm thời, không có lý do để khai báo chúng bên ngoài vòng lặp.
Holger

1
Hiệu quả hơn một chút khi khai báo tempbiến ngoài vòng lặp. Thủ XORthuật nên nhanh hơn so với sử dụng một tempbiến nhưng cách duy nhất để chắc chắn rằng nó thực hiện kiểm tra điểm chuẩn.
Dan Bray

25

Lớp bộ sưu tập có một phương thức hiệu quả để xáo trộn, có thể được sao chép, để không phụ thuộc vào nó:

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

để không phụ thuộc vào nó ? Tôi rất muốn phụ thuộc vào nó, nếu điều đó chỉ có thể.
shmosel

@shmosel Sau đó, hãy sử dụng nó. Hãy chắc chắn rằng bạn nhập lớp được yêu cầu và bạn đã chuyển đổi mảng thành một danh sách Arrays.asList. Bạn cũng phải chuyển đổi danh sách kết quả thành một mảng
KitKat

Bạn không thể sử dụng Arrays.asList()trên một mảng nguyên thủy. Và bạn sẽ không cần phải chuyển đổi nó trở lại bởi vì nó chỉ là một trình bao bọc.
shmosel

13

Nhìn vào Collectionslớp học, cụ thể shuffle(...).


8
Làm thế nào để bạn sử dụng lớp Bộ sưu tập này trong Android? Bạn cần thực hiện nhập khẩu đặc biệt (CRTL SHIFT O không hoạt động) để sử dụng?
Hubert

@Hubert nó nên là một phần của gói java.util. Đây là một phần của thư viện chuẩn kể từ v1.2.
MauganRa

3
Để làm cho câu trả lời của bạn trở nên khép kín hơn, nó nên chứa mã ví dụ. IE:import java.util.Collections; shuffle(solutionArray);
Stevoisiak

10

Đây là một giải pháp hoàn chỉnh sử dụng Collections.shufflephương pháp:

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

Lưu ý rằng nó bị ảnh hưởng do Java không có khả năng dịch trơn tru giữa int[]Integer[](và do đó int[]List<Integer>).


10

Bạn có một vài lựa chọn ở đây. Một danh sách là một chút khác nhau so với một mảng khi nói đến xáo trộn.

Như bạn có thể thấy bên dưới, một mảng nhanh hơn một danh sách và một mảng nguyên thủy nhanh hơn một mảng đối tượng.

Độ bền mẫu

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

Dưới đây, là ba triển khai khác nhau của một shuffle. Bạn chỉ nên sử dụng Collections.shuffle nếu bạn đang xử lý một bộ sưu tập. Không cần phải bọc mảng của bạn vào một bộ sưu tập chỉ để sắp xếp nó. Các phương pháp dưới đây rất đơn giản để thực hiện.

Lớp 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;

Phương pháp chính

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

Xáo trộn một danh sách chung

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

Xáo trộn một mảng chung

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

Xáo trộn một mảng nguyên thủy

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

Phương pháp tiện ích

Các phương thức tiện ích đơn giản để sao chép và chuyển đổi mảng thành danh sách và ngược lại.

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

Lớp phạm vi

Tạo một phạm vi các giá trị, tương tự như rangehàm của Python .

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

1
Bạn không định thời gian cho những thứ giống nhau và bạn chỉ định thời gian cho từng thứ một (sau đó đơn hàng của chúng sẽ được tính và bạn quên tối ưu hóa thời gian chạy). Bạn nên gọi range, toArraytoPrimitivetrước khi bất kỳ thời gian, và vòng lặp để có thể kết luận bất cứ điều gì (pseudo-code: làm nhiều lần {tạo danh sách, arr và iarr; thời gian xáo trộn danh sách, thời gian xáo trộn arr; thời gian xáo trộn iarr}). Kết quả của tôi: thứ 1 : list: 36017ns, arr: 28262ns, iarr: 23334ns. Thứ 100 : list: 18445ns, arr: 19995ns, iarr: 18657ns. Nó chỉ hiển thị int [] được tối ưu hóa trước (theo mã) nhưng chúng gần như tương đương với tối ưu hóa thời gian chạy.
syme

9

Sử dụng ArrayList<Integer>có thể giúp bạn giải quyết vấn đề xáo trộn mà không áp dụng nhiều logic và tiêu tốn ít thời gian hơn. Đây là những gì tôi đề nghị:

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

Có lẽ không phải là thứ hai - tiêu tốn ít thời gian hơn . Trong thực tế, điều này chắc chắn là chậm hơn so với các triển khai nguyên thủy ở trên.
Boris the Spider

1
Đối với ai đó sao chép mã, hãy xem "chu kỳ" i = 1 có thể bạn cần i = 0
Boris Karloff


5

Bạn có thể sử dụng java 8 ngay bây giờ:

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

2
Không có gì cụ thể về Java8 trong mã này. Điều này hoạt động kể từ Java2. Vâng, nó sẽ hoạt động, một khi bạn khắc phục sự không nhất quán giữa lần đầu tiên sử dụng listvà đột nhiên đề cập đến cardsList. Nhưng vì bạn cần tạo tạm thời list, cái mà bạn đã bỏ qua, không có lợi ích nào đối với Collections.shuffle(Arrays.asList(arr));cách tiếp cận được hiển thị nhiều lần ở đây. Mà cũng hoạt động kể từ Java2.
Holger

3

Đây là phiên bản Generics cho mảng:

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

Xem xét rằng ArrayList về cơ bản chỉ là một mảng, có thể nên làm việc với một ArrayList thay vì mảng rõ ràng và sử dụng Collections.shuffle (). Tuy nhiên, các bài kiểm tra hiệu năng không cho thấy bất kỳ sự khác biệt đáng kể nào giữa phần trên và 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

MathArrays.shuffle triển khai Apache Commons bị giới hạn ở int [] và hình phạt hiệu năng có thể là do trình tạo số ngẫu nhiên đang được sử dụng.


1
Dường như bạn có thể vượt qua new JDKRandomGenerator()để MathArrays.shuffle. Tôi tự hỏi làm thế nào điều đó ảnh hưởng đến hiệu suất?
Brandon

Trên thực tế ... có vẻ như MathArrays#shufflecó một sự phân bổ trong vòng lặp cốt lõi của nó : int targetIdx = new UniformIntegerDistribution(rng, start, i).sample();. Kỳ quái.
Brandon

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

Nhân tiện, tôi đã nhận thấy rằng mã này trả về một ar.length - 1số phần tử, vì vậy nếu mảng của bạn có 5 phần tử, mảng được xáo trộn mới sẽ có 4 phần tử. Điều này xảy ra bởi vì vòng lặp for nói i>0. Nếu bạn thay đổi thành i>=0, bạn sẽ có được tất cả các yếu tố xáo trộn.


Chỉ cần ngẩng cao đầu, bạn có thể muốn chuyển phần này sang phần bình luận câu hỏi của bạn, vì nó có thể sẽ bị gắn cờ nếu nó là câu trả lời của chính nó.
Jason D

1
Điều này dường như để trả lời câu hỏi, vì vậy tôi không chắc bạn đang nói gì về @JasonD
Sumurai8

1
Mã đúng, nhận xét sai. Nếu bạn thay đổi i>0thành i>=0, bạn lãng phí thời gian bằng cách hoán đổi phần tử 0với chính nó.
jcsahnwaldt phục hồi lại

3

Đây là một giải pháp sử dụng Apache Commons Math 3.x (chỉ cho mảng 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 [])

Ngoài ra, Apache Commons Lang 3.6 đã giới thiệu các phương thức xáo trộn mới cho ArrayUtilslớp (đối với các đối tượng và bất kỳ kiểu nguyên thủy nào).

ArrayUtils.shuffle(array);

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


3

Tôi thấy một số thông tin bỏ lỡ trong một số câu trả lời vì vậy tôi quyết định thêm một thông tin mới.

Java sưu tập Arrays.asList mất var-arg kiểu T (T ...). Nếu bạn truyền một mảng nguyên thủy (mảng int), phương thức asList sẽ suy ra và tạo ra một List<int[]>danh sách một phần tử (một phần tử là mảng nguyên thủy). nếu bạn xáo trộn danh sách một yếu tố này, nó sẽ không thay đổi bất kỳ điều gì.

Vì vậy, trước tiên bạn phải chuyển đổi mảng nguyên thủy của bạn sang mảng đối tượng Wrapper. để làm điều này, bạn có thể sử dụng ArrayUtils.toObjectphương thức từ apache.commons.lang. sau đó chuyển mảng đã tạo vào Danh sách và hoàn thành việc xáo trộn đó.

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

3

Đây là một cách khác để xáo trộn một danh sách

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

Chọn một số ngẫu nhiên từ danh sách gốc và lưu nó vào danh sách khác. Sau đó xóa số đó khỏi danh sách ban đầu. Kích thước của danh sách gốc sẽ tiếp tục giảm một cho đến khi tất cả các yếu tố được chuyển sang danh sách mới.


2

Một giải pháp đơn giản cho Groovy:

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

Điều này sẽ sắp xếp tất cả các phần tử của danh sách mảng một cách ngẫu nhiên để lưu trữ kết quả mong muốn của việc xáo trộn tất cả các phần tử.



1

Tôi đang cân nhắc về câu hỏi rất phổ biến này bởi vì không ai đã viết một phiên bản sao chép ngẫu nhiên. Phong cách được vay mượn rất nhiều Arrays.java, bởi vì ngày nay ai không nắm bắt được công nghệ Java? Chung và intthực hiện bao gồm.

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

Đây là thuật toán shuffle knuth.

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

Có một cách khác nữa, chưa đăng

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

cách đó dễ dàng hơn, phụ thuộc vào bối cảnh


1

Giải pháp đơn giản nhất cho Shuffling ngẫu nhiên này trong một mảng.

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
  1. Hộp từ int[]đếnInteger[]
  2. Gói một mảng vào một danh sách với Arrays.asListphương thức
  3. Xáo trộn với Collections.shufflephương pháp

    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]

1

Mã đơn giản nhất để xáo trộn:

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

Sử dụng lớp ngẫu nhiên

  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
      } 

  }

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

Vui lòng thêm một số mô tả liên quan đến câu trả lời của bạn.
ankit suthar

0
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

tương tự mà không sử dụng trao đổi 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 base on size
    }
    solutionArray[n-1] = arr.get(0);

0

Một trong những giải pháp là sử dụng hoán vị để tính toán trước tất cả các hoán vị và được lưu trữ trong ArrayList

Java 8 đã giới thiệu một phương thức mới, ints (), trong lớp java.util.Random. Phương thức ints () trả về một luồng giá trị int giả ngẫu nhiên không giới hạn. Bạn có thể giới hạn các số ngẫu nhiên giữa một phạm vi được chỉ định bằng cách cung cấp các giá trị tối thiểu và tối đa.

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

Với sự trợ giúp của việc tạo số ngẫu nhiên, Bạn có thể lặp qua vòng lặp và trao đổi với chỉ số hiện tại với số ngẫu nhiên .. Đó là cách bạn có thể tạo một số ngẫu nhiên với độ phức tạp không gian O (1).


0

Không có giải pháp ngẫu nhiên:

   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));
    }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.