Generate random number without duplicate in certai

2019-05-28 18:14发布

问题:

I'm currently creating an app and it will generate random numbers. So each time it will generate three numbers num1, num2 and num3. These number should not be duplicate. For example if num1 = 1 than num2 and num3 cannot be equal to 1. I've tried this code where it will display three different number ranging from 0-2. And its working. However I would want to generate random number ranging from 1-3, 2-4, 3-5 and so on. So how can I achieve this by using the code below. Please help me since I'm new to this. Thank you.

for(int i=0; i<images.length; i++)
{
        num[i] = (int)(Math.random()*3);

        if (i == 0)
        {
        if(num[i]== 0)
            images[i].setImageResource(R.drawable.zero);
        else if(num[i]==1)
            images[i].setImageResource(R.drawable.one);
        else
            images[i].setImageResource(R.drawable.two);
        }

        else
        {
            while (num[i] ==  num[i-1] || num[i] == num[0] )
                num[i] = (int)(Math.random()*3);


        if(num[i]==0)
            images[i].setImageResource(R.drawable.zero);
        else if(num[i]==1)
            images[i].setImageResource(R.drawable.one);
        else
            images[i].setImageResource(R.drawable.two);

        }
    }

回答1:

Create a list if all numbers in the range, then shuffle the list:

List<Integer> numbers = new ArrayList<>();
// eg for range 3-5
for (int i = 3; i <= 5; i++)
    numbers.add(i);
Collections.shuffle(numbers);

Now use them in their new (random) order.

Unless your range is very large (millions) this will work fine.


Java8 version:

List<Integer> numbers = IntStream.rangeClosed(3, 5).boxed().collect(Collectors.toList());
Collections.shuffle(numbers);


回答2:

Well, you could store your numbers an an ArrayList<>. Every time you generate a random number, see if the ArrayList<> contains the number. If it does, generate another number and repeat the process.

Better yet, use a Set <>.



回答3:

To get numbers ranging from 1-3, 2-4, 3-5, etc, change this

num[i] = (int)(Math.random()*3);

to this

num[i] = rand.nextInt(2) + 1 + i;

You'll need to import Random and add Random rand = new Random(); before using it.



回答4:

The formula to generate random number in the range is :

    Random rn = new Random();
    int range = maximum - minimum + 1;
    int randomNum =  rn.nextInt(range) + minimum;

so in one line you can generate as like this

    int num1 = new Random().nextInt(3-1+1) + 1;
    int num2 = new Random().nextInt(4-2+1) + 1;
    int num3 = new Random().nextInt(5-2+1) + 1;

or

    num[i] = new Random.nextInt(range[i]) + 1 + i;

and then you can do your logic stuff to set the resource. Happy Coding :)



回答5:

The best possible and most efficient way to generate and store unique numbers would be to create a HashSet that holds your data. Generate the number and then try to add it to the HashSet. If the add method returns false, then it means that the number already exists in the set and hence re-generate a number. The advantage of using this method over the ArrayList is that this has a time complexity of O(1) while using the contains() method (from ArrayList) would result in a time complexity of O(n) - efficiency decreases as size increases.



回答6:

int base = (int)Math.random(); System.out.print(base);

int change = ((int)Math.random()) % 3;

if(change == 0) { change++; System.out.print(base + 1); System.out.println(base + 2); }

else { System.out.print(base + 2); System.out.println(base + 1); }



回答7:

You can also use Random number generation to fill a HashSet for a fixed range.



回答8:

I know it's late, but could be helpful for future reference. You can create your own custom Random class:

//Generates random integers without repetition between two given numbers both inclusive
public class Random {
    private int start;
    private int end;
    private Stack<Integer> numbers = new Stack<>();
    public Random(int start, int end){
        this.start = start;
        this.end = end;
    }
    private void loadNumbers(){
         for (int i=start;i<=end;i++){
                numbers.push(i);
            }
         Collections.shuffle(numbers);
    }
    public int nextInt(){
        if (numbers.empty()) loadNumbers();
        return numbers.pop();
    }
}

And use it like:

Random rand = new Random(1,20);
for(int i=0; i<100;i++){
    System.out.print(rand.nextInt()+ " ");
}


回答9:

Reduce the total amount every run, and appropriately increment the result.

static int[] randomRange(Random random, int cap, int count) {
    assert count < cap && count > 0 && cap > 0;
    int[] output = new int[count];
    // initial placeholder. use 0x7FFFFFFF for convenience is also OK.
    Arrays.fill(output, -1);
    for(int i = 0; i < count; i++) {
        // you only have (cap - i) options left
        int r = random.nextInt(cap - i);
        // iterate through a sorted array
        for(int got : output) {
            // ignore placeholders
            if(got != -1 && got <= r) {
                // the generated random int counts number of not-yet-picked ints
                r++;
            }
        }
        // add to array in a sorted manner
        addToArray(output, r);
    }
    return output;
}

static void addToArray(int[] array, int value) {
    for(int i = 1; i <= array.length; i++) {
        if(i == array.length || array[i] >= value) {
            // shift smaller values one place left
            // this includes -1. If you use 0x7FFFFFFF,
            // you may have to sort the array the other way round.
            System.arraycopy(array, 1, array, 0, i - 1);
            array[i - 1] = value;
            return;
        }
    }
}

This algorithm has a disadvantage that its output is sorted. It is, of course, also possible to keep track of two arrays, one sorted (for increment) and one unsorted (for return).

The above code snippet was tested through cap = 20, count = 10 and cap = 20, count = 20 twice each.



回答10:

Integer[] a = new Integer[3];
Random r = new Random();
for (int i = 0; i < a.length; i++) { 
        a[i] = r.nextInt(3-1) + 1;  
}
Collections.shuffle(Arrays.asList(a), r);