สับแบบสุ่มของอาร์เรย์


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
ไม่ใช่คำตอบสำหรับคำถามต้นฉบับจริงๆ แต่ MathArrays.shuffle จากไลบรารี commons-math3 ทำงานได้
sandris

1
นี่ไม่ใช่หัวข้อที่เพียงพอที่จะรับประกันคำตอบ แต่ฉันจำบทความที่เจ๋งจริง ๆ จากหนังสือ "Graphics Gems" ที่พูดถึงการสำรวจอาร์เรย์ในลำดับสุ่มหลอก ในใจของฉันที่ต้องเต้นสับเปลี่ยนข้อมูลในสถานที่แรก การใช้งาน C สามารถพบได้ที่นี่github.com/erich666/GraphicsGems/blob/master/gems/Dissolve.c
Lennart Rolland

ดูคำถามที่เกี่ยวข้องอย่างใกล้ชิดนี้: stackoverflow.com/questions/2450954/…
Pierz

คำตอบ:


263

การใช้คอลเล็กชันเพื่อสับเปลี่ยนอาเรย์ประเภทแบบดั้งเดิมเป็นบิตของ overkill ...

มันง่ายพอที่จะใช้ฟังก์ชั่นของคุณเองตัวอย่างเช่นการสับเปลี่ยน 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;
    }
  }
}

26
มาก nitpick เล็กน้อย แต่คุณก็สามารถใช้แทนprintln() println("")ชัดเจนในเจตนาผมคิดว่า :)
แวนส์

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 สับเปลี่ยน การสับเปลี่ยนฟิชเชอร์ - เยตส์ดั้งเดิมทำงานในเวลา 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));
FindOutIslam

@Timmos คุณผิด Arrays.asList ล้อมรอบอาเรย์ดั้งเดิมและปรับเปลี่ยนอาเรย์เดิม นั่นเป็นเหตุผลที่คุณไม่สามารถเพิ่มหรือลบเพราะอาร์เรย์มีขนาดคงที่
Nand

@ ไม่แน่ใจว่าฉันคิดอะไรอยู่ แต่มองไปที่ซอร์สโค้ดจริง ๆ แล้ววิธีการ 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 การสลับองค์ประกอบด้วยตัวเองนั้นสามารถทำได้ในการสั่งซื้อแบบสุ่ม การไม่เข้าใจสิ่งนี้ทำให้ Enigma อ่อนแอลงและช่วยให้ Alan Turing แตกได้ en.wikipedia.org/wiki/…
Ellen Spertus

4
xorเคล็ดลับคือการแลกเปลี่ยนที่ดีสำหรับการลงทะเบียนของ 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

ดูที่ชั้นโดยเฉพาะCollectionsshuffle(...)


8
คุณใช้คลาส Collections นี้ใน Android ได้อย่างไร คุณจำเป็นต้องนำเข้าพิเศษ (CRTL SHIFT O ไม่ทำงาน) เพื่อใช้งานหรือไม่
Hubert

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

โปรดทราบว่ามันมีปัญหาเนื่องจากการที่ Java ไม่สามารถแปลระหว่างint[]และInteger[](และดังนั้นint[]และList<Integer>) อย่างราบรื่น


10

คุณมีสองทางเลือกที่นี่ รายการแตกต่างจากอาเรย์เมื่อเทียบกับการสับ

อย่างที่คุณเห็นด้านล่างอาเรย์นั้นเร็วกว่ารายการและอาเรย์แบบดั้งเดิมนั้นเร็วกว่าอาเรย์วัตถุ

ตัวอย่างระยะเวลา

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

ด้านล่างนี้เป็นการนำการสับเปลี่ยนที่แตกต่างกันสามแบบ คุณควรใช้ Collections.shuffle เฉพาะเมื่อคุณจัดการกับคอลเล็กชัน ไม่จำเป็นต้องล้อมอาร์เรย์ของคุณไว้ในคอลเล็กชันเพื่อเรียงลำดับ วิธีการด้านล่างนั้นใช้ง่ายมาก

ShuffleUtil Class

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

คลาสของช่วง

สร้างช่วงของค่าคล้ายกับrangeฟังก์ชั่นของ Python

    // ================================================================
    // 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ก่อนระยะเวลาใด ๆ และห่วงที่จะสามารถที่จะสรุปอะไรเลย (หลอกรหัส: ไม่หลายครั้ง {สร้างรายการ, arr และ iarr; เวลารายการสับ; เวลาสับ ARR; เวลาสับ iarr}) ผลของฉัน: list: 36017ns, arr: 28262ns, iarr: 23334ns1: ครบรอบ list: 18445ns, arr: 19995ns, iarr: 18657ns100: มันแสดงให้เห็นว่า 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);

อาจจะไม่ได้หลัง - ใช้เวลาน้อยลง ในความเป็นจริงนี้ช้ากว่าการใช้งานดั้งเดิมข้างต้นอย่างแน่นอน
Boris the Spider

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

นี่คือรุ่น 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 [] และอาจมีการปรับประสิทธิภาพเนื่องจากมีการใช้ตัวสร้างตัวเลขแบบสุ่ม


1
ดูเหมือนว่าคุณจะผ่านnew JDKRandomGenerator()ไปMathArrays.shuffleได้ ฉันสงสัยว่ามันส่งผลต่อประสิทธิภาพการทำงานอย่างไร
แบรนดอน

ที่จริง ... ดูเหมือนว่าจะ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 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 ใช้เวลา var-หาเรื่องประเภท (T ...)T หากคุณผ่านอาร์เรย์ดั้งเดิม (int array) วิธี asList จะอนุมานและสร้างList<int[]>ซึ่งเป็นรายการองค์ประกอบหนึ่งรายการ (องค์ประกอบหนึ่งคืออาร์เรย์ดั้งเดิม) ถ้าคุณสับเปลี่ยนรายการองค์ประกอบนี้มันจะไม่เปลี่ยนแปลงอะไรเลย

ดังนั้นก่อนอื่นคุณต้องแปลงอาเรย์ดั้งเดิมของคุณเป็นออบเจ็กต์ 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!

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

ฉันกำลังชั่งน้ำหนักในคำถามยอดนิยมนี้เพราะไม่มีใครเขียนรุ่นที่คัดลอกมาได้ สไตล์เป็นสิ่งที่ยืมมาอย่างมาก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;
   }

1

นี่คืออัลกอริทึมสับเปลี่ยนของ 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]);
    }
}

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

ที่คล้ายกันโดยไม่ต้องใช้ 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);

0

หนึ่งในวิธีการแก้ปัญหาคือการใช้การเปลี่ยนแปลงเพื่อคำนวณพีชคณิตทั้งหมดก่อนและเก็บไว้ใน ArrayList

Java 8 แนะนำวิธีการใหม่ ints () ในคลาส java.util.Random เมธอด ints () ส่งคืนสตรีมค่า pseudorandom ที่ไม่ จำกัด คุณสามารถ จำกัด จำนวนสุ่มระหว่างช่วงที่ระบุได้โดยระบุค่าต่ำสุดและค่าสูงสุด

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.