Creating unique random numbers

2019-02-19 00:52发布

问题:

I have created the following method so as to create unique random numbers . (This unique values belong to the nodes of a tree):

  static Random rand = new Random();
public static ArrayList<Node> go(int n) {
    ArrayList<Node> list = new ArrayList<Node>();
    ArrayList<Integer> numList = new ArrayList<Integer>();
    // TODO Auto-generated method stub
    for(int i = 1; i<=5; i++)
    {
        int number = rand.nextInt(10)+1;
        if(list.size()>0 && !check(list,number))
        {
            i--;
            continue;
        }
        numList.add(number);
        Node node = new Node();
        node.data = number;
        list.add(node);
    }
     int w  = 0;
    for (Node d : list) {
        System.out.println(w+": "+d.data);
        w++;
    }
    return list;

}
  private static boolean check(ArrayList<Node> list, int num) {
    // TODO Auto-generated method stub
    boolean b = false;
    /*if(list.size()==0)
        return true;
    */
    for (Node node : list) {
        if(node.data == num)
            b = false;
        else
            b = true;
    }
    return b;
}

But it doesn’t create unique numbers and there are still duplicates in my list. Like :

0: 10
1: 1 
2: 10 
3: 5 
4: 6 

回答1:

The problem is that you don't stop the for loop inside the check function if it finds a duplicated number. The loop continues and b can change back to true.

What you should do is for example:

  private static boolean check(ArrayList<Node> list, int num) {
    for (Node node : list) {
        if(node.data == num)
            return false;
    }
    return true;
}


回答2:

Jón Trausti Arason has your answer, but...

Since you have a finite number of allowed values (integers), and since you don't want the same one picked more than once, perhaps it would be easier to just shuffle an array of the allowed values. Then you could just pick off the next value from the array and not worry about checking every time whether it's a repeat.

In your example selecting five values between one and ten, you could start with an array {1,2,3,4,5,6,7,8,9,10} and run it through a shuffle to rearrange it to something else like {3,4,7,1,10,9,5,8,2,6}. Take the first five values out of that resulting array with no worries about repeats.



回答3:

In your check method, this looks a bit dodgy:

if (node.data == num) 
  b = false;
else
  b = true

Surely once you've found a match (e.g. b = false) you want to return? Otherwise the next time around the loop b might be set to true. To simplify a bit, if you want to check whether an item is in a collection you can do list.contains(element)



回答4:

You "forget" to use the numList that you've prepared.

This code should work fine:

static Random rand = new Random();

public static ArrayList<Node> go(int n) {
    ArrayList<Node> list = new ArrayList<Node>();
    ArrayList<Integer> numList = new ArrayList<Integer>();

    for (int i = 1; i <= 5; i++) {
        int number = rand.nextInt(10) + 1;
        if (numList.contains(number)) {
            i--;
            continue;
        }
        numList.add(number);
        Node node = new Node();
        node.data = number;
        list.add(node);
    }
    int w = 0;
    for (Node d : list) {
        System.out.println(w + ": " + d.data);
        w++;
    }
    return list;

}


回答5:

To illustrate on @eaj's point.

public static List<Node> go(int n) {
    List<Integer> numbers = new ArrayList<Integer>();
    for (int i = 1; i <= 10; i++) numbers.add(i);
    Collections.shuffle(numbers);
    List<Node> nodes = new ArrayList<Node>();
    for (Integer data : numbers.subList(0, 5))
        nodes.add(new Node(data)); // use a constructor for Node.
    for (int w = 0; w < nodes.size(); w++)
        System.out.println(w + ": " + nodes.get(w).data);
    return nodes;
}


回答6:

Your check function is wrong. Currently, it simply returns whether the last element matches num. You want to declare true (e.g. with return true;) once you find a match.

In fact, you can do everything without b. And I'm sure you can use list's contain method instead.



回答7:

You should change your check method to something like:

  private static boolean check(ArrayList<Node> list, int num)
  {
    for (Node node : list)
        if (node.data == num)
            return false;

    return true;
  }

In this way you go over the list and return false as soon as you find an equal element. If you are able to finish the loop without returning then no duplicates are found and you can return true.



回答8:

This is my solution:

import java.util.ArrayList;
import java.util.Collections;


public class comboGenerator {

    public static void main(String[] args) {


    ArrayList<Integer> $combo = new ArrayList<Integer>();       // init. array list combo for randomization


        while ($combo.size() < 6) {  
            int rand = (int) (Math.random()*49+1);          // make new random number 1-49
            if (!$combo.contains(rand)){                    // check if we have that number in array list,{
            $combo.add(rand);                               // if there is no such number then add it to array list
            Collections.sort($combo);                       // sort the array list small >> large
            }
        }

    System.out.println("Random combination " + $combo);

}   
}

And you CAN'T get same numbers!



标签: java random