次の配列をランダムにシャッフルする必要があります。
int[] solutionArray = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1};
それを行う機能はありますか?
次の配列をランダムにシャッフルする必要があります。
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;
}
}
}
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));
以下は、機能的で効率的なフィッシャー・イエーツのシャッフル配列関数です。
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
変数が、それはベンチマークテストを実行するようにしてくださいする唯一の方法。
コレクションクラスには、シャッフルするための効率的なメソッドがあり、それに依存しないようにコピーできます。
/**
* 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);
}
}
Javaがint[]
and 間Integer[]
(したがってint[]
and 間)をスムーズに変換できないために影響を受けることに注意してくださいList<Integer>
。
ここにはいくつかのオプションがあります。リストは、シャッフルに関して配列とは少し異なります。
以下に示すように、配列はリストよりも高速で、プリミティブ配列はオブジェクト配列よりも高速です。
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");
}
};
}
}
}
range
、toArray
かつtoPrimitive
(:数回はない{時間シャッフルiarrリスト、ARRとiarrを生成し、時間リストをシャッフル;時間ARRをシャッフル}擬似コード)任意のタイミング、およびループの前に何を締結することができるように。私の結果:1番目: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配列)を渡すと、asListメソッドは、List<int[]>
は、1つの要素のリストであるます(1つの要素はプリミティブ配列です)。この1つの要素のリストをシャッフルしても、何も変わりません。
したがって、最初にプリミティブ配列をWrapperオブジェクト配列に変換する必要があります。これにはArrayUtils.toObject
、apache.commons.langのメソッドを使用できます。次に、生成された配列をリストに渡し、最後にそれをシャッフルします。
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ずつ減少し続けます。
Groovyのシンプルなソリューション:
solutionArray.sort{ new Random().nextInt() }
これにより、配列リストのすべての要素がランダムにソートされ、すべての要素をシャッフルした望ましい結果がアーカイブされます。
Guavaを使用Ints.asList()
すると、次のように簡単です。
Collections.shuffle(Ints.asList(array));
誰もがシャッフルコピーバージョンを作成したことがないため、この非常に人気のある質問を検討しています。スタイルはから大いに借りられています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;
}
これは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]);
}
}
配列内のこのランダムシャッフルの最も簡単な解決策。
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);
解決策の1つは、順列を使用してすべての順列を事前計算し、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));
}