创建没有重复的随机数

Woo*_*ung 82 java random

在这种情况下,MAX只有5,所以我可以逐个检查重复,但我怎么能以更简单的方式做到这一点?例如,如果MAX的值为20,该怎么办?谢谢.

int MAX = 5;

for (i = 1 , i <= MAX; i++)
{
        drawNum[1] = (int)(Math.random()*MAX)+1;

        while (drawNum[2] == drawNum[1])
        {
             drawNum[2] = (int)(Math.random()*MAX)+1;
        }
        while ((drawNum[3] == drawNum[1]) || (drawNum[3] == drawNum[2]) )
        {
             drawNum[3] = (int)(Math.random()*MAX)+1;
        }
        while ((drawNum[4] == drawNum[1]) || (drawNum[4] == drawNum[2]) || (drawNum[4] == drawNum[3]) )
        {
             drawNum[4] = (int)(Math.random()*MAX)+1;
        }
        while ((drawNum[5] == drawNum[1]) ||
               (drawNum[5] == drawNum[2]) ||
               (drawNum[5] == drawNum[3]) ||
               (drawNum[5] == drawNum[4]) )
        {
             drawNum[5] = (int)(Math.random()*MAX)+1;
        }

}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 143

最简单的方法是创建一个可能的数字列表(1..20或其他)然后用它们随机播放Collections.shuffle.然后只需要你想要的许多元素.如果您的范围等于最终所需的元素数量(例如,用于洗牌一副牌),这是很好的.

如果你想要(比方说)1个10,000范围内的10个随机元素,那么效果不会很好 - 你最终会不必要地做很多工作.此时,保留到目前为止生成的一组值可能更好,并且只是在循环中生成数字,直到下一个尚未存在:

if (max < numbersNeeded)
{
    throw new IllegalArgumentException("Can't ask for more numbers than are available");
}
Random rng = new Random(); // Ideally just create one instance globally
// Note: use LinkedHashSet to maintain insertion order
Set<Integer> generated = new LinkedHashSet<Integer>();
while (generated.size() < numbersNeeded)
{
    Integer next = rng.nextInt(max) + 1;
    // As we're adding to a set, this will automatically do a containment check
    generated.add(next);
}
Run Code Online (Sandbox Code Playgroud)

但要小心设置选项 - 我非常谨慎地使用LinkedHashSet它,因为它维护了我们关心的插入顺序.

另一种选择是通过每次缩小范围并补偿现有值来始终取得进展.因此,例如,假设您想要0到9范围内的3个值.在第一次迭代中,您将生成0..9范围内的任何数字 - 假设您生成4.

在第二次迭代中,您将生成0..8范围内的数字.如果生成的数字小于4,则按原样保留...否则添加一个.这样你得到的结果范围是0..9没有4.假设我们得到7那样的方式.

在第三次迭代中,您将生成0..7范围内的数字.如果生成的数字小于4,则保持原样.如果它是4或5,你就加一个.如果它是6或7,你将添加两个.这样结果范围是0..9,没有4或6.


Cat*_*hwa 18

这是我怎么做的

import java.util.ArrayList;
import java.util.Random;

public class Test {
    public static void main(String[] args) {
        int size = 20;

        ArrayList<Integer> list = new ArrayList<Integer>(size);
        for(int i = 1; i <= size; i++) {
            list.add(i);
        }

        Random rand = new Random();
        while(list.size() > 0) {
            int index = rand.nextInt(list.size());
            System.out.println("Selected: "+list.remove(index));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

正如受人尊敬的Skeet先生指出:
如果n是您想要选择的随机选择数字的数量,N是可供选择的数字的总样本空间:

  1. 如果n << N,您应该只存储您选择的数字并检查列表以查看所选的数字是否在其中.
  2. 如果n ~ = N,您应该使用我的方法,填充包含整个样本空间的列表,然后在选择它们时从中删除数字.


小智 13

//random numbers are 0,1,2,3 
ArrayList<Integer> numbers = new ArrayList<Integer>();   
Random randomGenerator = new Random();
while (numbers.size() < 4) {

    int random = randomGenerator .nextInt(4);
    if (!numbers.contains(random)) {
        numbers.add(random);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 对于大量数据来说,这会产生可怕的性能。ArrayList.contains 正在迭代列表。使用 Set 会更干净——您不需要检查它是否包含,只需添加,性能会更好。 (2认同)

Eug*_*ene 8

这会简单得多java-8

Stream.generate(new Random()::ints)
            .flatMap(IntStream::boxed)
            .distinct()
            .limit(16) // whatever limit you might need
            .toArray(Integer[]::new);
Run Code Online (Sandbox Code Playgroud)


fel*_*ipe 5

还有另一种用 LFSR 做“随机”有序数字的方法,看看:

http://en.wikipedia.org/wiki/Linear_feedback_shift_register

使用这种技术,您可以通过索引获得有序的随机数,并确保值不重复。

但这些不是真正的随机数,因为随机生成是确定性的。

但是根据您的情况,您可以使用此技术减少使用改组时随机数生成的处理量。

这是java中的LFSR算法,(我把它带到了我不记得的地方):

public final class LFSR {
    private static final int M = 15;

    // hard-coded for 15-bits
    private static final int[] TAPS = {14, 15};

    private final boolean[] bits = new boolean[M + 1];

    public LFSR() {
        this((int)System.currentTimeMillis());
    }

    public LFSR(int seed) {
        for(int i = 0; i < M; i++) {
            bits[i] = (((1 << i) & seed) >>> i) == 1;
        }
    }

    /* generate a random int uniformly on the interval [-2^31 + 1, 2^31 - 1] */
    public short nextShort() {
        //printBits();

        // calculate the integer value from the registers
        short next = 0;
        for(int i = 0; i < M; i++) {
            next |= (bits[i] ? 1 : 0) << i;
        }

        // allow for zero without allowing for -2^31
        if (next < 0) next++;

        // calculate the last register from all the preceding
        bits[M] = false;
        for(int i = 0; i < TAPS.length; i++) {
            bits[M] ^= bits[M - TAPS[i]];
        }

        // shift all the registers
        for(int i = 0; i < M; i++) {
            bits[i] = bits[i + 1];
        }

        return next;
    }

    /** returns random double uniformly over [0, 1) */
    public double nextDouble() {
        return ((nextShort() / (Integer.MAX_VALUE + 1.0)) + 1.0) / 2.0;
    }

    /** returns random boolean */
    public boolean nextBoolean() {
        return nextShort() >= 0;
    }

    public void printBits() {
        System.out.print(bits[M] ? 1 : 0);
        System.out.print(" -> ");
        for(int i = M - 1; i >= 0; i--) {
            System.out.print(bits[i] ? 1 : 0);
        }
        System.out.println();
    }


    public static void main(String[] args) {
        LFSR rng = new LFSR();
        Vector<Short> vec = new Vector<Short>();
        for(int i = 0; i <= 32766; i++) {
            short next = rng.nextShort();
            // just testing/asserting to make 
            // sure the number doesn't repeat on a given list
            if (vec.contains(next))
                throw new RuntimeException("Index repeat: " + i);
            vec.add(next);
            System.out.println(next);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Car*_*uez 5

另一种方法,它允许您指定多少个号码想sizeminmax值返回的数字

public static int getRandomInt(int min, int max) {
    Random random = new Random();

    return random.nextInt((max - min) + 1) + min;
}

public static ArrayList<Integer> getRandomNonRepeatingIntegers(int size, int min,
        int max) {
    ArrayList<Integer> numbers = new ArrayList<Integer>();

    while (numbers.size() < size) {
        int random = getRandomInt(min, max);

        if (!numbers.contains(random)) {
            numbers.add(random);
        }
    }

    return numbers;
}
Run Code Online (Sandbox Code Playgroud)

使用它返回 0 到 25 之间的 7 个数字。

    ArrayList<Integer> list = getRandomNonRepeatingIntegers(7, 0, 25);
    for (int i = 0; i < list.size(); i++) {
        System.out.println("" + list.get(i));
    }
Run Code Online (Sandbox Code Playgroud)