简体   繁体   中英

How to generate 6 different random numbers in java

I want to generate 6 different random numbers by using Math.random and store them into an array. How can I make sure that they are different? I know I need to use for-loop to check the array but how...

This is the range. I only need numbers between 1 and 49. ( 1 + (int) (Math.random() * 49) )

In Java 8:

final int[] ints = new Random().ints(1, 50).distinct().limit(6).toArray();

In Java 7:

public static void main(final String[] args) throws Exception {
    final Random random = new Random();
    final Set<Integer> intSet = new HashSet<>();
    while (intSet.size() < 6) {
        intSet.add(random.nextInt(49) + 1);
    }
    final int[] ints = new int[intSet.size()];
    final Iterator<Integer> iter = intSet.iterator();
    for (int i = 0; iter.hasNext(); ++i) {
        ints[i] = iter.next();
    }
    System.out.println(Arrays.toString(ints));
}

Just a little messier. Not helped by the fact that it's pretty tedious to unbox the Set<Integer> into an int[] .

It should be noted that this solution should be fine of the number of required values is significantly smaller than the range. As 1..49 is quite a lot larger than 6 you're fine. Otherwise performance rapidly degrades.

Create a list containing the numbers 1 to 49.

Create a random number x between 0 and the size of the list, take the number being at index x in the list, and remove it from the list.

Repeat the previous step 5 times. And you're done. Note that java.util.Random has a nextInt(int max) method that you should use instead of Math.random() .

Note regarding performance: this solution has an advantage compared to the "try until you get 6 different numbers" various solutions: it runs in a O(n) time. It doesn't matter much for 6 unique numbers out of 50, but if you want to get 48 or 49 unique random numbers out of 50, you'll start seeing a difference, because you might have to generate many random numbers before getting one that isn't already in the set.

EDIT:

to reduce the cost induced by the removal of the elements in the list, you could instead simply replace the element at index x with the last element of the list (and at the second iteration, with the element at size - 2, etc.)

Generate any 6 numbers (not necessarily different). Order them.

a1 <= a2 <= a3 <= a4 <= a5 <= a6

Now take these 6 numbers

a1 < a2 + 1 < a3 + 2 < a4 + 3 < a5 + 4 < a6 + 5

These 6 are different and random.

The idea of this construct comes from some combinatorial proofs.

Its advantage is that it's simple, fast, and deterministic.
I think the time complexity is O(count*log(count)) .
I wonder if it can be improved.

import java.util.TreeMap;

public class Test005 {

    public static void main(String[] args) {
        int count = 6;
        int min = 1;
        int max = 49;

        // random number mapped to the count of its occurrences
        TreeMap<Integer, Integer> mp = new TreeMap<Integer, Integer>();
        for (int i=0; i<count; i++){
             int d = ( min + (int) (Math.random() * (max-count+1)) );
             if (!mp.containsKey(d)){
                 mp.put(d, 0);
             }
             mp.put(d, mp.get(d) + 1);
        }

        // now ensure the output numbers are different
        int j = 0;
        for (int num : mp.keySet()){
            int cnt = mp.get(num);
            for (int i=0; i<cnt; i++){
                System.out.println(num + j);
                j++;
            }
        }
    }

}

You can use a Set .

Set<Integer> s = new HashSet<>();
while(s.size() != 6){
   s.add(1 + (int) (Math.random() * 49));
}

Integer[] arr = s.toArray(new Integer[s.size()]);

This is enough to do this in your case because the number of distinct random numbers is relatively small compared to the size of the range you generate them.

Otherwise I would go with @JBNizet approach.

I've just came up with a small idea for Java 8-.

Set<Integer> set = new LinkedHashSet<>();
while(set.size() != 6)
    set.add(rnd.nextInt(49) + 1);

Instead of checking that the array has no duplicates, you can use a bit more smartness while generating the numbers, such that uniqueness is enforced at the outset.

  1. Create a boolean[] as long as your range (49 entries);
  2. generate a random number from the full range;
  3. put that number into your output array;
  4. "cross out" the corresponding index in the boolean[] ;
  5. now generate another random number, but curtail the range by one (now 48);
  6. instead of directly using that number as output, scan your boolean[] , counting all the non-crossed entries. Stop when you reach the count equal to the random number generated in step 5. The number corresponding to that entry is your output number;
  7. go to step 4.

in your case n=6

     public static int[] chooseAny(int n){
        int[] lottery = new int[n];
        int[] chooseFrom = new int[49];
        for(int i=1 ; i <= 49 ; i++)
            chooseFrom[i-1] = i;
        Random rand = new Random();
        int N = 49;
        int index;
        for(int i=0 ; i < n ; i++){
            //pick random index
            index = rand.nextInt(N);
            lottery[i] = chooseFrom[index];
            chooseFrom[index] = chooseFrom[N-1];
            N--;
        }
        return lottery;
    }

Just keep generating numbers and adding them to the array as long as they are unique; psuedocode:

num = genNextRand()

For (array length)
    If (num not in array)
        addToArray()

Repeat while length not equal 6

Create a variable last ; initialize it to 0 .

Next, in a loop x from 0 to 5, create a random number between last +1 and 49-6+ x . Store this number in a list, and set last to the number generated this way.

You will end up with an ordered list of 6 random numbers in the range of 1..49 with no repeats.

That code generate numbers from 6 to 0 and save in ArrayList.

If generated number was duplicated the program generate numbers again.

If generated number is different that number is added.

Code:

private ArrayList<Integer> arraylist = new ArrayList<Integer>();

private Random rand = new Random();

public void insertNumber() {
    while (true) {
        int i = generateNumber();
        if(!isGenerateNumberExists(i)){
            addNumber(i);
            break;
        }
    }
}
//Generate numbers
private int generateNumber() {
    return rand.nextInt(6);
}
//Confirm if that number exists
private boolean isGenerateNumberExists(int y) {
    for (int num : arraylist) {
        if (num == y) {
            return true;
        }
    }
    return false;
}
//Add number to arrayList
private void addNumber(int x) {
    arraylist.add(x);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM