次の配列をランダムにシャッフルする必要があります。
int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};
それをする機能はありますか?
コレクションを使用してプリミティブ型の配列をシャッフルするのは、やり過ぎです。
たとえば Fisher – Yatesシャッフル を使用して、関数を自分で実装するのは簡単です。
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;
}
}
}
これはArrayList
を使った簡単な方法です:
List<Integer> solution = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
solution.add(i);
}
Collections.shuffle(solution);
これが有効で効率的な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;
}
}
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;
}
}
Collections
クラス、特にshuffle(...)
を見てください。
ここではいくつかの選択肢があります。リストはシャッフルに関しては配列とは少し異なります。
以下に示すように、配列はリストよりも速く、プリミティブ配列はオブジェクト配列よりも高速です。
List<Integer> Shuffle: 43133ns
Integer[] Shuffle: 31884ns
int[] Shuffle: 25377ns
以下は、シャッフルの3つの異なる実装です。コレクションを扱う場合は、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");
}
};
}
}
}
これがCollections.shuffle
アプローチを使用した完全な解決策です:
public static void shuffleArray(int[] array) {
List<Integer> list = new ArrayList<>();
for (int i : array) {
list.add(i);
}
Collections.shuffle(list);
for (int i = 0; i < list.size(); i++) {
array[i] = list.get(i);
}
}
Javaがint[]
とInteger[]
(したがってint[]
とList<Integer>
)の間でスムーズに変換できないために問題があることに注意してください。
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);
これが配列用のGenericsバージョンです。
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 []に制限されており、パフォーマンスの低下はおそらく乱数ジェネレータが使用されていることによるものです。
これはApache Commons Math 3.xを使った解決策です(int []配列のみ)。
MathArrays.shuffle(array);
あるいは、Apache Commons Lang 3.6では、(オブジェクトおよびあらゆるプリミティブ型の)ArrayUtils
クラスに新しいシャッフルメソッドが導入されました。
ArrayUtils.shuffle(array);
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
に変更すると、すべての要素がシャッフルされます。
私はいくつかの答えでいくつかのミス情報を見たので、私は新しいものを追加することにしました。
JavaコレクションArrays.asListは型T (T ...)
のvar-argを取ります。プリミティブ配列(int array)を渡すと、asListメソッドはList<int[]>
を推論して生成します。これは1要素のリストです(1要素はプリミティブ配列です)。この1つの要素リストをシャッフルしても、何も変更されません。
だから、まずあなたはプリミティブ配列を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!
これはリストをシャッフルするもう一つの方法です
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;
}
元のリストから乱数を選択して別のリストに保存します。元のリストから番号を削除します。元のリストのサイズは、すべての要素が新しいリストに移動されるまで1ずつ減少し続けます。
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]
Groovyのための簡単な解決策:
solutionArray.sort{ new Random().nextInt() }
これにより、配列リストのすべての要素がランダムにソートされ、すべての要素をシャッフルした結果が得られます。
配列内のこのランダムシャフリングのための最も簡単な解決策。
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]);
}
シャッフルする最も簡単なコード:
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));
}
}
シャッフルコピーバージョンを書いた人はいないので、この非常に人気のある質問を検討します。スタイルは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;
}
まだ投稿していない、別の方法もあります
//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);
}
そのようにすれば、文脈にもよりますが、より簡単になります。
これはナースシャッフルアルゴリズムです。
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つは、並べ替えを使用してすべての並べ替えを事前計算し、ArrayListに格納することです。
Java 8では、Java.util.Randomクラスに新しいメソッドints()が導入されました。 ints()メソッドは、疑似乱数int値の無制限のストリームを返します。最小値と最大値を指定することで、指定された範囲内の乱数を制限できます。
Random genRandom = new Random();
int num = genRandom.nextInt(arr.length);
乱数を生成することで、ループを反復して現在のインデックスと乱数を交換することができます。これがO(1)のスペースの複雑さで乱数を生成する方法です。
Guavaの Ints.asList()
を使うと、とても簡単です。
Collections.shuffle(Ints.asList(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);
}
}
}
スワップ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);
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);
}
}