다음 배열을 무작위로 섞어 야합니다.
int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};
그렇게하는 기능이 있습니까?
List<int[]>
포함하는 하나 개의 항목. 사용하여 이것을 달성하는 방법에 대한 내 대답 을 참조하십시오 Collections.shuffle()
.
다음 배열을 무작위로 섞어 야합니다.
int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};
그렇게하는 기능이 있습니까?
List<int[]>
포함하는 하나 개의 항목. 사용하여 이것을 달성하는 방법에 대한 내 대답 을 참조하십시오 Collections.shuffle()
.
답변:
콜렉션을 사용하여 기본 유형의 배열을 섞는 것은 약간 과잉입니다 ...
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;
}
}
}
println()
대신 대신 사용할 수 있습니다 println("")
. 의도가 더 명확하다고 생각합니다 :)
Collections.shuffle(Arrays.asList(array))
는 작동하지 않습니다 . 생각한대로 Arrays.asList(array)
반환 Collection<int[]>
하지 않기 때문 Collection<Integer>
입니다.
다음은 간단한 방법입니다 ArrayList
.
List<Integer> solution = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
solution.add(i);
}
Collections.shuffle(solution);
Collectons.shuffle(Arrays.asList(solutionArray));
작동하고 효율적인 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
논쟁의 여지가 허용 index
하고 i
잠재적으로 동일 할 수 있습니다.
xor
트릭은 CPU에 스왑 명령이없고 사용 가능한 레지스터가 없을 때 CPU 레지스터를 스왑하는 데 유용하지만 루프 내부의 배열 요소를 스왑하는 경우 아무런 이점이 없습니다. 임시 지역 변수의 경우 루프 외부에서 변수를 선언 할 이유가 없습니다.
temp
루프 외부 에서 변수 를 선언하는 것이 약간 더 효율적 입니다. XOR
트릭은 빨리 사용하는 것보다해야 temp
확인이 벤치 마크 테스트를 수행 할 수 변수하지만 유일한 방법.
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;
}
}
Arrays.asList
. 결과 목록도 배열로 변환해야합니다
Arrays.asList()
기본 배열 에는 사용할 수 없습니다 . 래퍼 일 뿐이므로 다시 변환 할 필요가 없습니다.
Collections
수업을 살펴보십시오 shuffle(...)
. 구체적으로 .
java.util
. v1.2 이후 표준 라이브러리의 일부입니다.
import java.util.Collections; shuffle(solutionArray);
이 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>
).
여기 몇 가지 옵션이 있습니다. 셔플과 관련하여 목록은 배열과 약간 다릅니다.
아래에서 볼 수 있듯이 배열은 목록보다 빠르며 기본 배열은 객체 배열보다 빠릅니다.
List<Integer> Shuffle: 43133ns
Integer[] Shuffle: 31884ns
int[] Shuffle: 25377ns
다음은 셔플의 세 가지 다른 구현입니다. 컬렉션을 다룰 때는 Collections.shuffle 만 사용해야합니다. 정렬하기 위해 배열을 컬렉션으로 묶을 필요는 없습니다. 아래의 방법은 구현이 매우 간단합니다.
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");
}
};
}
}
}
range
, toArray
그리고 toPrimitive
어떤 타이밍, 루프 전에 어떤 결론을 내릴 수 있도록 (의사 코드 : 여러 번 {목록을 생성, 언 및 iarr, 시간이 목록을 셔플, 시간 셔플 편곡, 시간 iarr 셔플} 않습니다). 내 결과 : 1st : list: 36017ns, arr: 28262ns, iarr: 23334ns
. 100 일 : list: 18445ns, arr: 19995ns, iarr: 18657ns
. int []가 (코드에 의해) 사전 최적화되어 있음을 보여 주지만 런타임 최적화와 거의 동일합니다.
를 사용하면 ArrayList<Integer>
많은 논리를 적용하지 않고 시간을 덜 소비하지 않고도 셔플 링 문제를 해결할 수 있습니다. 여기 내가 제안하는 것이 있습니다.
ArrayList<Integer> x = new ArrayList<Integer>();
for(int i=1; i<=add.length(); i++)
{
x.add(i);
}
Collections.shuffle(x);
다음 코드는 배열에서 임의 순서를 달성합니다.
// 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/
이제 Java 8을 사용할 수 있습니다.
Collections.addAll(list, arr);
Collections.shuffle(list);
cardsList.toArray(arr);
list
하고 갑자기 참조하는 것 사이의 불일치를 수정하면 작동 합니다 cardsList
. 그러나 list
당신이 생략 한 임시를 만들어야하기 때문에 Collections.shuffle(Arrays.asList(arr));
여기에 여러 번 표시된 접근법에 비해 이점이 없습니다 . Java2부터 작동합니다.
다음은 배열의 제네릭 버전입니다.
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();
. 기괴한.
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
하면 모든 요소가 섞입니다.
i>0
하면 i>=0
요소 0
를 자신과 교체 하여 시간을 낭비 하게됩니다.
다음은 Apache Commons Math 3.x를 사용하는 솔루션입니다 (int [] 배열에만 해당).
MathArrays.shuffle(array);
또는 Apache Commons Lang 3.6이 ArrayUtils
클래스에 새로운 셔플 메소드를 도입했습니다 (객체 및 기본 유형).
ArrayUtils.shuffle(array);
나는 일부 답변에서 누락 된 정보를 보았으므로 새로운 것을 추가하기로 결정했습니다.
Java 콜렉션 Arrays.asList는 T 유형의 var-arg를 사용합니다 (T ...)
. 프리미티브 배열 (int array)을 전달하면 asList 메소드가List<int[]>
하나의 요소 목록 인 하나의 요소 목록 합니다 (하나의 요소는 기본 배열). 이 하나의 요소 목록을 섞으면 아무 것도 변경되지 않습니다.
따라서 먼저 기본 배열을 래퍼 객체 배열로 변환해야합니다. 이를 위해 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!
리스트를 섞는 다른 방법이 있습니다.
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;
}
원래 목록에서 임의의 숫자를 선택하여 다른 목록에 저장 한 다음 원래 목록에서 숫자를 제거하십시오. 원래 목록의 크기는 모든 요소가 새 목록으로 이동 될 때까지 하나씩 감소합니다.
구아바를 사용하면 다음 Ints.asList()
과 같이 간단합니다.
Collections.shuffle(Ints.asList(array));
나는 셔플 카피 버전을 작성한 사람이 없기 때문에이 매우 인기있는 질문에 집중하고 있습니다. 요즘 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;
}
이것은 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]);
}
}
이 랜덤 셔플 링을위한 가장 간단한 솔루션입니다.
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]);
}
int[]
에Integer[]
Arrays.asList
메소드를 사용하여 배열을 목록으로 랩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]
가장 간단한 셔플 코드 :
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));
}
}
랜덤 클래스 사용
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
}
}
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);
}
}
}
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);
}
}
스왑 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);
해결책 중 하나는 순열을 사용하여 모든 순열을 미리 계산하고 ArrayList에 저장하는 것입니다.
Java 8은 java.util.Random 클래스에 새로운 메소드 ints ()를 도입했습니다. ints () 메소드는 의사 난수 int 값의 무제한 스트림을 리턴합니다. 최소값과 최대 값을 제공하여 지정된 범위 사이의 난수를 제한 할 수 있습니다.
Random genRandom = new Random();
int num = genRandom.nextInt(arr.length);
난수 생성을 통해 루프를 반복하고 난수를 사용하여 현재 색인과 스왑 할 수 있습니다. O (1) 공간 복잡도로 난수를 생성하는 방법입니다.
무작위 솔루션이없는 경우 :
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));
}