Zufälliges Mischen eines Arrays

232

Ich muss das folgende Array zufällig mischen:

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

Gibt es eine Funktion dafür?

Hubert
quelle
5
Dies ist die SDK-Methode, nach der Sie suchen. Collections.shuffle (Arrays.asList (Array));
Louis Hong
2
@ Louie Nein, das funktioniert nicht. Das würde List<int[]>einen Eintrag mit einem Eintrag erstellen . Siehe meine Antwort für den Weg, um dies mit zu erreichen Collections.shuffle().
Duncan Jones
2
Keine wirkliche Antwort auf die ursprüngliche Frage, aber MathArrays.shuffle aus der commons-math3-Bibliothek erledigt den Job.
Sandris
1
Dies ist nicht thematisch genug, um eine Antwort zu rechtfertigen, aber ich erinnere mich an einen wirklich coolen Artikel aus dem Buch "Graphics Gems", in dem es darum ging, ein Array in pseudozufälliger Reihenfolge zu durchlaufen. In meinen Augen ist es besser, die Daten überhaupt erst mischen zu müssen. Die C-Implementierung finden Sie hier github.com/erich666/GraphicsGems/blob/master/gems/Dissolve.c
Lennart Rolland
Siehe auch diese eng verwandte Frage: stackoverflow.com/questions/2450954/…
Pierz

Antworten:

263

Die Verwendung von Sammlungen zum Mischen einer Reihe primitiver Typen ist ein wenig übertrieben ...

Es ist einfach genug, die Funktion selbst zu implementieren, indem Sie beispielsweise das Fisher-Yates-Shuffle verwenden :

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;
    }
  }
}
PhiLho
quelle
26
Extrem trivialer Nitpick, aber Sie können einfach println()statt verwenden println(""). Klarer in der Absicht denke ich :)
Cowan
55
Es wäre viel besser, Collections.shuffle (Arrays.asList (Array)) zu verwenden. dann mische dich selbst.
Louis Hong
21
@Louie Collections.shuffle(Arrays.asList(array))funktioniert nicht, weil die Arrays.asList(array)Rückkehr Collection<int[]>nicht so ist, Collection<Integer>wie Sie gedacht haben.
Adam Stelmaszczyk
15
@exhuma Denn wenn Sie ein Array von Tausenden oder Millionen primitiver Werte sortieren müssen, ist das Einschließen jedes einzelnen in ein Objekt, nur um eine Sortierung durchzuführen, sowohl im Speicher als auch in der CPU etwas kostspielig.
PhiLho
14
Dies ist nicht das Fisher-Yates-Shuffle. Dies nennt man Durstenfeld Shuffle . Das ursprüngliche Fisher-Yates-Shuffle läuft in O (n ^ 2) -Zeit, was extrem langsam ist.
Pacerier
164

Hier ist ein einfacher Weg mit ArrayList:

List<Integer> solution = new ArrayList<>();
for (int i = 1; i <= 6; i++) {
    solution.add(i);
}
Collections.shuffle(solution);
methodin
quelle
1
Sie können einfachCollectons.shuffle(Arrays.asList(solutionArray));
FindOutIslamNow
@Timmos Du liegst falsch. Arrays.asList umschließt das ursprüngliche Array und ändert es durch Ändern des ursprünglichen Arrays. Aus diesem Grund können Sie keine Arrays hinzufügen oder entfernen, da diese eine feste Größe haben.
Nand
@Nand nicht sicher, was ich dachte, aber beim Betrachten des Quellcodes erstellt die Arrays.asList-Methode tatsächlich eine ArrayList, die von dem angegebenen Array unterstützt wird. Vielen Dank für den Hinweis. Mein vorheriger Kommentar wurde gelöscht (konnte nicht bearbeitet werden).
Timmos
100

Hier ist eine funktionierende und effiziente Fisher-Yates-Shuffle-Array-Funktion:

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

oder

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;
    }
}
Dan Bray
quelle
1
Abgestimmt, weil ich eine Lösung brauchte, die nicht den hohen Aufwand hatte, eine Sammlung von Ganzzahlen zu
erstellen
2
Hat die zweite Implementierung nicht das Potenzial, mit einem eigenen Index zu tauschen? random.nextInt(int bound)ist exklusiv, aber es i + 1als Argument zu geben, würde es erlauben indexund imöglicherweise dasselbe sein.
bmcentee148
21
@ bmcentee148 Das Austauschen eines Elements mit sich selbst ist in zufälliger Reihenfolge zulässig. Das Nichtverstehen schwächte das Rätsel und half Alan Turing, es zu knacken. en.wikipedia.org/wiki/…
Ellen Spertus
4
Der xorTrick ist großartig, um CPU-Register auszutauschen, wenn die CPU keinen Swap-Befehl hat und es keine freien Register gibt, aber für das Austauschen von Array-Elementen innerhalb einer Schleife sehe ich keinen Vorteil. Für die temporären lokalen Variablen gibt es keinen Grund, sie außerhalb der Schleife zu deklarieren.
Holger
1
Es ist etwas effizienter, die tempVariable außerhalb der Schleife zu deklarieren . Der XORTrick sollte schneller sein als die Verwendung einer tempVariablen, aber der einzige Weg, um sicherzugehen, dass ein Benchmark-Test durchgeführt wird.
Dan Bray
25

Die Collections- Klasse verfügt über eine effiziente Methode zum Mischen, die kopiert werden kann, um nicht davon abhängig zu sein:

/**
 * 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;
    }
}
KitKat
quelle
um nicht davon abhängig zu sein ? Ich würde mich viel lieber darauf verlassen, wenn das nur möglich wäre.
Shmosel
@shmosel Dann zögern Sie nicht, es zu benutzen. Stellen Sie sicher, dass Sie die erforderliche Klasse importieren und das Array in eine Liste mit konvertiert haben Arrays.asList. Sie müssen die resultierende Liste auch in ein Array konvertieren
KitKat
Sie können nicht Arrays.asList()für ein primitives Array verwenden. Und Sie müssten es nicht zurückkonvertieren, weil es nur ein Wrapper ist.
Shmosel
13

Schauen Sie sich Collectionsspeziell die Klasse an shuffle(...).

Dave
quelle
8
Wie benutzt man diese Sammlungsklasse in Android? Sie müssen einen speziellen Import durchführen (CRTL SHIFT O funktioniert nicht), um ihn zu verwenden?
Hubert
@ Hubert sollte es Teil des Pakets sein java.util. Es ist seit v1.2 Teil der Standardbibliothek.
MauganRa
3
Um Ihre Antwort eigenständiger zu gestalten, sollte sie Beispielcode enthalten. IE:import java.util.Collections; shuffle(solutionArray);
Stevoisiak
10

Hier ist eine Komplettlösung mit dem Collections.shuffleAnsatz:

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

Beachten Sie, dass es unter der Unfähigkeit von Java leidet, reibungslos zwischen int[]und Integer[](und damit int[]und List<Integer>) zu übersetzen.

Duncan Jones
quelle
10

Sie haben hier ein paar Möglichkeiten. Eine Liste unterscheidet sich beim Mischen ein wenig von einem Array.

Wie Sie unten sehen können, ist ein Array schneller als eine Liste und ein primitives Array ist schneller als ein Objektarray.

Probendauer

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

Im Folgenden finden Sie drei verschiedene Implementierungen eines Shuffle. Sie sollten Collections.shuffle nur verwenden, wenn Sie mit einer Sammlung arbeiten. Sie müssen Ihr Array nicht in eine Sammlung einbinden, um es zu sortieren. Die folgenden Methoden sind sehr einfach zu implementieren.

ShuffleUtil-Klasse

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;

Hauptmethode

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

Eine generische Liste mischen

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

Ein generisches Array mischen

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

Mischen eines primitiven Arrays

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

Dienstprogrammmethoden

Einfache Dienstprogrammmethoden zum Kopieren und Konvertieren von Arrays in Listen und umgekehrt.

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

Bereichsklasse

Erzeugt einen Wertebereich, ähnlich der Python- rangeFunktion.

    // ================================================================
    // 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");
                }
            };
        }
    }
}
Mr. Polywhirl
quelle
1
Sie planen nicht die gleichen Dinge und Sie planen jedes nur einmal (dann zählt ihre Reihenfolge und Sie vergessen die Laufzeitoptimierung). Sie sollten und vor jedem Timing und einer Schleife aufrufen range, um etwas abschließen zu können (Pseudocode: mehrmals ausführen {Liste generieren, arr und iarr; Zeitmischungsliste; Zeitmixing arr; Zeitmixing iarr}). Meine Ergebnisse: 1.: . 100.: . Es zeigt nur, dass int [] voroptimiert ist (per Code), aber sie entsprechen fast der Laufzeitoptimierung. toArraytoPrimitivelist: 36017ns, arr: 28262ns, iarr: 23334nslist: 18445ns, arr: 19995ns, iarr: 18657ns
Syme
9

Die Verwendung ArrayList<Integer>kann Ihnen dabei helfen, das Problem des Mischens zu lösen, ohne viel Logik anzuwenden und weniger Zeit zu verbrauchen. Folgendes schlage ich vor:

ArrayList<Integer> x = new ArrayList<Integer>();
for(int i=1; i<=add.length(); i++)
{
    x.add(i);
}
Collections.shuffle(x);
SalmaanKhan
quelle
Wahrscheinlich nicht Letzteres - weniger Zeitaufwand . Tatsächlich ist dies sicherlich langsamer als die obigen primitiven Implementierungen.
Boris die Spinne
1
Wenn jemand den Code kopiert, achten Sie auf den "for-Zyklus" i = 1, vielleicht brauchen Sie i = 0
Boris Karloff
5

Sie können jetzt Java 8 verwenden:

Collections.addAll(list, arr);
Collections.shuffle(list);
cardsList.toArray(arr);
Иван Николайчук
quelle
2
Dieser Code enthält nichts Java8-spezifisches. Dies funktioniert seit Java2. Nun, es würde funktionieren, wenn Sie die Inkonsistenz zwischen der ersten Verwendung listund dem plötzlichen Verweisen behoben haben cardsList. Da Sie jedoch das temporäre Element erstellen müssen list, das Sie weggelassen haben, hat der Collections.shuffle(Arrays.asList(arr));hier mehrmals gezeigte Ansatz keinen Vorteil . Welches funktioniert auch seit Java2.
Holger
3

Hier ist eine generische Version für Arrays:

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

Da ArrayList im Grunde genommen nur ein Array ist, kann es ratsam sein, mit einer ArrayList anstelle des expliziten Arrays zu arbeiten und Collections.shuffle () zu verwenden. Leistungstests zeigen jedoch keinen signifikanten Unterschied zwischen den oben genannten und 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

Die Apache Commons-Implementierung MathArrays.shuffle ist auf int [] beschränkt, und der Leistungsverlust ist wahrscheinlich auf den verwendeten Zufallszahlengenerator zurückzuführen.

user1050755
quelle
1
Es sieht aus wie Sie passieren new JDKRandomGenerator()zu MathArrays.shuffle. Ich frage mich, wie sich das auf die Leistung auswirkt.
Brandon
Eigentlich ... sieht es so aus, als hätte MathArrays#shufflees eine Zuordnung in seiner Kernschleife : int targetIdx = new UniformIntegerDistribution(rng, start, i).sample();. Bizarr.
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;
}

Übrigens ist mir aufgefallen, dass dieser Code eine ar.length - 1Reihe von Elementen zurückgibt. Wenn Ihr Array also 5 Elemente enthält, enthält das neue gemischte Array 4 Elemente. Dies geschieht, weil die for-Schleife sagt i>0. Wenn Sie zu wechseln i>=0, werden alle Elemente gemischt.

Cristiane Dos Santos Costa
quelle
Nur einen Kopf hoch, möchten Sie dies möglicherweise in den Kommentarbereich Ihrer Frage verschieben, da diese wahrscheinlich markiert wird, wenn sie als eigene Antwort belassen wird.
Jason D
1
Dies scheint die Frage zu beantworten, daher bin ich mir nicht sicher, wovon Sie sprechen @JasonD
Sumurai8
1
Der Code ist korrekt, der Kommentar ist falsch. Wenn Sie ändern i>0zu i>=0, verschwenden Sie Zeit durch das Element Austausch 0mit sich.
jcsahnwaldt Reinstate Monica
3

Hier ist eine Lösung mit Apache Commons Math 3.x (nur für int [] Arrays):

MathArrays.shuffle(array);

http://commons.apache.org/proper/commons-math/javadocs/api-3.6.1/org/apache/commons/math3/util/MathArrays.html#shuffle (int [])

Alternativ führte Apache Commons Lang 3.6 neue Shuffle-Methoden in die ArrayUtilsKlasse ein (für Objekte und jeden primitiven Typ).

ArrayUtils.shuffle(array);

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

Emmanuel Bourg
quelle
3

Ich habe in einigen Antworten einige fehlende Informationen gesehen, also habe ich beschlossen, eine neue hinzuzufügen.

Java Sammlungen Arrays.asList nimmt var-arg vom Typ T (T ...). Wenn Sie ein primitives Array (int array) übergeben, leitet die asList-Methode ein ab und generiert einList<int[]> eine Liste mit einem Element ab (das eine Element ist das primitive Array). Wenn Sie diese Liste mit einem Element mischen, ändert dies nichts.

Zuerst müssen Sie Ihr primitives Array in ein Wrapper-Objektarray konvertieren. ArrayUtils.toObjectHierfür können Sie die Methode aus apache.commons.lang verwenden. Übergeben Sie dann das generierte Array an eine Liste und mischen Sie diese endgültig.

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

Hier ist eine andere Möglichkeit, eine Liste zu mischen

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

Wählen Sie eine Zufallszahl aus der Originalliste und speichern Sie sie in einer anderen Liste. Entfernen Sie dann die Nummer aus der Originalliste. Die Größe der Originalliste wird um eins verringert, bis alle Elemente in die neue Liste verschoben wurden.

PS5
quelle
2

Eine einfache Lösung für Groovy:

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

Dadurch werden alle Elemente der Array-Liste zufällig sortiert, wodurch das gewünschte Ergebnis des Mischens aller Elemente archiviert wird.

Hans Kristian
quelle
2

Mit Guaven ist Ints.asList()es so einfach wie:

Collections.shuffle(Ints.asList(array));
BeeOnRope
quelle
1

Ich überlege mir diese sehr beliebte Frage, weil niemand eine Shuffle-Copy-Version geschrieben hat. Stil ist stark entlehnt Arrays.java, denn wer plündert heutzutage nicht die Java-Technologie? Generika und intImplementierungen enthalten.

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

Dies ist der Knuth-Shuffle-Algorithmus.

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]);
    }
}
BufBills
quelle
1

Es gibt auch einen anderen Weg, noch nicht zu posten

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

auf diese Weise einfacher, abhängig vom Kontext

Marcelo Ferreira
quelle
1

Die einfachste Lösung für dieses zufällige Mischen in einem Array.

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]);
}
Archit Goel
quelle
1
  1. Box von int[]bisInteger[]
  2. Wickeln Sie ein Array mit der Arrays.asListMethode in eine Liste
  3. Mit Collections.shuffleMethode mischen

    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]
YujiSoftware
quelle
1

Einfachster zu mischender Code:

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));       
    }
}
suraj
quelle
1

Verwenden der Zufallsklasse

  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
      } 

  }
Fiel Muhongo
quelle
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);
    }
}
}
Nikil Gupta
quelle
Bitte fügen Sie eine verwandte Beschreibung zu Ihrer Antwort hinzu.
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);
    }

}
Aurobind Singh
quelle
0

ähnlich ohne Swap 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);
Digitebs
quelle
0

Eine der Lösungen besteht darin, die Permutation zu verwenden, um alle Permutationen vorab zu berechnen und in der ArrayList zu speichern

Java 8 führte eine neue Methode, ints (), in die Klasse java.util.Random ein. Die Methode ints () gibt einen unbegrenzten Strom von pseudozufälligen int-Werten zurück. Sie können die Zufallszahlen zwischen einem bestimmten Bereich begrenzen, indem Sie den Minimal- und den Maximalwert angeben.

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

Mit Hilfe der Generierung der Zufallszahl können Sie die Schleife durchlaufen und mit dem aktuellen Index gegen die Zufallszahl tauschen. Auf diese Weise können Sie eine Zufallszahl mit O (1) -Raumkomplexität generieren.


quelle
0

Ohne zufällige Lösung:

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