배열의 무작위 셔플 링


232

다음 배열을 무작위로 섞어 야합니다.

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

그렇게하는 기능이 있습니까?


5
이것은 찾고있는 SDK 메소드입니다. Collections.shuffle (Arrays.asList (array));
Louis Hong

2
@Louie 아니요, 작동하지 않습니다. 즉, 만들 것 List<int[]>포함하는 하나 개의 항목. 사용하여 이것을 달성하는 방법에 대한 내 대답 을 참조하십시오 Collections.shuffle().
Duncan Jones

2
실제로 원래 질문에 대한 대답은 아니지만 commons-math3 라이브러리의 MathArrays.shuffle이 작업을 수행합니다.
sandris

1
이것은 주제에 대한 답변이 충분하지 않지만 "Graphics Gems"책에서 의사 난수 순서로 배열을 순회하는 것에 대해 이야기 한 멋진 기사를 기억합니다. 내 생각에는 실제로 데이터를 처음부터 섞어 야합니다. 는 C-구현은 여기에서 발견된다 github.com/erich666/GraphicsGems/blob/master/gems/Dissolve.c
레나 롤랑

또한이 밀접하게 관련된 질문을보십시오 : stackoverflow.com/questions/2450954/…
Pierz

답변:


263

콜렉션을 사용하여 기본 유형의 배열을 섞는 것은 약간 과잉입니다 ...

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

26
매우 사소한 nitpick이지만 println()대신 대신 사용할 수 있습니다 println(""). 의도가 더 명확하다고 생각합니다 :)
Cowan

55
Collections.shuffle (Arrays.asList (array));를 사용하는 것이 훨씬 좋습니다. 그런 다음 자신을 뒤섞습니다.
Louis Hong

21
@Louie Collections.shuffle(Arrays.asList(array))는 작동하지 않습니다 . 생각한대로 Arrays.asList(array)반환 Collection<int[]>하지 않기 때문 Collection<Integer>입니다.
Adam Stelmaszczyk

15
@exhuma 정렬 할 수천 또는 수백만 개의 기본 값 배열이있는 경우 정렬을 수행하기 위해 오브젝트에 각 값을 랩핑하면 메모리와 CPU 모두에서 약간의 비용이 듭니다.
PhiLho

14
이것은 Fisher-Yates 셔플 이 아닙니다 . 이것을 Durstenfeld shuffle 이라고 합니다. 원래 피셔-야테 셔플은 O (n ^ 2) 시간에 실행되며 매우 느립니다.
Pacerier

164

다음은 간단한 방법입니다 ArrayList.

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

1
당신은 간단하게Collectons.shuffle(Arrays.asList(solutionArray));
FindOutIslamNow

@Timmos 당신이 틀 렸습니다. Arrays.asList는 원래 배열을 감싸서 수정하면 원래 배열을 수정합니다. 따라서 배열의 크기가 고정되어 있으므로 추가하거나 제거 할 수 없습니다.
낸드

@ 내가 생각한 것을 확신하지 못하지만 소스 코드를 보면 실제로 Arrays.asList 메소드는 주어진 배열에 의해 지원되는 ArrayList를 만듭니다. 지적 해 주셔서 감사합니다. 이전 댓글을 삭제했습니다 (편집 할 수 없음).
Timmos

100

작동하고 효율적인 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;
    }
}

1
정수 컬렉션을 만드는 높은 오버 헤드가없는 솔루션이 필요했기 때문에 투표함
mwk

2
두 번째 구현은 자체 인덱스와 교환 할 가능성이 없습니까? random.nextInt(int bound)독점적이지만 i + 1논쟁의 여지가 허용 index하고 i잠재적으로 동일 할 수 있습니다.
bmcentee148

21
@ bmcentee148 임의의 순서로 요소를 교체하는 것은 허용됩니다. 이것을 이해하지 못하면 수수께끼가 약해지고 Alan Turing이 그것을 깨뜨리는 데 도움이되었습니다. en.wikipedia.org/wiki/…
Ellen Spertus 2016 년

4
xor트릭은 CPU에 스왑 명령이없고 사용 가능한 레지스터가 없을 때 CPU 레지스터를 스왑하는 데 유용하지만 루프 내부의 배열 요소를 스왑하는 경우 아무런 이점이 없습니다. 임시 지역 변수의 경우 루프 외부에서 변수를 선언 할 이유가 없습니다.
Holger

1
temp루프 외부 에서 변수 를 선언하는 것이 약간 더 효율적 입니다. XOR트릭은 빨리 사용하는 것보다해야 temp확인이 벤치 마크 테스트를 수행 할 수 변수하지만 유일한 방법.
Dan Bray

25

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

@shmosel 그런 다음 자유롭게 사용하십시오. 필요한 클래스를 가져오고을 사용하여 배열을 목록으로 변환했는지 확인하십시오 Arrays.asList. 결과 목록도 배열로 변환해야합니다
KitKat

Arrays.asList()기본 배열 에는 사용할 수 없습니다 . 래퍼 일 뿐이므로 다시 변환 할 필요가 없습니다.
shmosel

13

Collections수업을 살펴보십시오 shuffle(...). 구체적으로 .


8
Android에서이 Collections 클래스를 어떻게 사용합니까? 특수 가져 오기를 수행해야합니다 (CRTL SHIFT O가 작동하지 않음).
Hubert

@ 허버트 그것은 패키지의 일부가되어야합니다 java.util . v1.2 이후 표준 라이브러리의 일부입니다.
MauganRa

3
답변을보다 독립적으로 만들려면 예제 코드가 포함되어 있어야합니다. IE :import java.util.Collections; shuffle(solutionArray);
Stevoisiak

10

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

참고이 때문에 원활 사이에 번역하는 자바의 무능력을 앓고 int[]Integer[](따라서 int[]List<Integer>).


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

1
당신은 같은 것을 타이밍하지 않고 각각 한 번만 타이밍합니다 (그러면 순서가 중요하며 런타임 최적화를 잊어 버립니다). 당신은 호출해야합니다 range, toArray그리고 toPrimitive어떤 타이밍, 루프 전에 어떤 결론을 내릴 수 있도록 (의사 코드 : 여러 번 {목록을 생성, 언 및 iarr, 시간이 목록을 셔플, 시간 셔플 편곡, 시간 iarr 셔플} 않습니다). 내 결과 : 1st : list: 36017ns, arr: 28262ns, iarr: 23334ns. 100 일 : list: 18445ns, arr: 19995ns, iarr: 18657ns. int []가 (코드에 의해) 사전 최적화되어 있음을 보여 주지만 런타임 최적화와 거의 동일합니다.
syme

9

를 사용하면 ArrayList<Integer>많은 논리를 적용하지 않고 시간을 덜 소비하지 않고도 셔플 링 문제를 해결할 수 있습니다. 여기 내가 제안하는 것이 있습니다.

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

아마 후자가 더 적은 시간을 소비 하지는 않을 것 입니다. 실제로 이것은 위의 기본 구현보다 확실히 느립니다.
거미 보리스

1
누군가 코드를 복사하려면 "주기"를보십시오. i = 1 아마도 i = 0이 필요할 수 있습니다.
Boris Karloff


5

이제 Java 8을 사용할 수 있습니다.

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

2
이 코드에는 Java8 고유의 것이 없습니다. 이것은 Java2부터 작동합니다. 글쎄, 처음 사용 list하고 갑자기 참조하는 것 사이의 불일치를 수정하면 작동 합니다 cardsList. 그러나 list당신이 생략 한 임시를 만들어야하기 때문에 Collections.shuffle(Arrays.asList(arr));여기에 여러 번 표시된 접근법에 비해 이점이 없습니다 . Java2부터 작동합니다.
Holger

3

다음은 배열의 제네릭 버전입니다.

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 []로 제한되며 사용 된 난수 생성기 때문에 성능이 저하 될 수 있습니다.


1
당신이 전달할 수있는 것 같습니다 new JDKRandomGenerator()MathArrays.shuffle. 이것이 성능에 어떤 영향을 미치는지 궁금합니다.
Brandon

실제로 ... MathArrays#shuffle핵심 루프에 할당이있는 것 같습니다 : int targetIdx = new UniformIntegerDistribution(rng, start, i).sample();. 기괴한.
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;
}

그런데이 코드는 ar.length - 1많은 요소를 반환 하므로 배열에 5 개의 요소가 있으면 새로운 셔플 배열에는 4 개의 요소가 있습니다. 이것은 for 루프가 말하기 때문에 발생합니다 i>0. 로 변경 i>=0하면 모든 요소가 섞입니다.


머릿속으로, 질문의 코멘트 섹션으로 옮기고 싶을 수도 있습니다. 왜냐하면 자체 답변으로 남겨지면 플래그가 표시되기 때문입니다.
Jason D

1
이것은 질문에 대답하는 것처럼 보이므로 @JasonD에 대해 무엇을 이야기하고 있는지 잘 모르겠습니다.
Sumurai8

1
코드가 정확하고 주석이 잘못되었습니다. 로 변경 i>0하면 i>=0요소 0를 자신과 교체 하여 시간을 낭비 하게됩니다.
jcsahnwaldt Reinstate Monica

3

다음은 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-


3

나는 일부 답변에서 누락 된 정보를 보았으므로 새로운 것을 추가하기로 결정했습니다.

Java 콜렉션 Arrays.asList는 T 유형의 var-arg를 사용합니다 (T ...). 프리미티브 배열 (int array)을 전달하면 asList 메소드가List<int[]> 하나의 요소 목록 인 하나의 요소 목록 합니다 (하나의 요소는 기본 배열). 이 하나의 요소 목록을 섞으면 아무 것도 변경되지 않습니다.

따라서 먼저 기본 배열을 래퍼 객체 배열로 변환해야합니다. 이를 위해 ArrayUtils.toObjectapache.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

리스트를 섞는 다른 방법이 있습니다.

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

Groovy를위한 간단한 솔루션 :

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

이렇게하면 배열 목록의 모든 요소가 무작위로 정렬되어 원하는 모든 요소를 ​​섞은 결과를 보관합니다.



1

나는 셔플 카피 버전을 작성한 사람이 없기 때문에이 매우 인기있는 질문에 집중하고 있습니다. 요즘 Java 기술을 약화 시키지 않는Arrays.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

이것은 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

아직 게시하지 않은 다른 방법이 있습니다.

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

이 랜덤 셔플 링을위한 가장 간단한 솔루션입니다.

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. 상자 에서 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]

1

가장 간단한 셔플 코드 :

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

랜덤 클래스 사용

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

답변과 관련된 설명을 추가하십시오.
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

스왑 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

해결책 중 하나는 순열을 사용하여 모든 순열을 미리 계산하고 ArrayList에 저장하는 것입니다.

Java 8은 java.util.Random 클래스에 새로운 메소드 ints ()를 도입했습니다. ints () 메소드는 의사 난수 int 값의 무제한 스트림을 리턴합니다. 최소값과 최대 값을 제공하여 지정된 범위 사이의 난수를 제한 할 수 있습니다.

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

난수 생성을 통해 루프를 반복하고 난수를 사용하여 현재 색인과 스왑 할 수 있습니다. O (1) 공간 복잡도로 난수를 생성하는 방법입니다.


0

무작위 솔루션이없는 경우 :

   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));
    }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.