tags:

views:

178

answers:

2

The task is this: generate k distinct positive numbers less than n without duplication.

My method is the following.

First create array size of k where we should write these numbers:

int a[] = new int[k];

//Now I am going to create another array where I check if (at given number
//position is 1 then generate number again, else put this number in an
//array and continue cycle.

I put a piece here of code and explanations.

int a[]=new int[k];
int t[]=new int[n+1];
Random r=new Random();
for (int i==0;i<t.length;i++){
    t[i]=0;//initialize it to zero
}

int m=0;//initialize it also
for (int i=0;i<a.length;i++){
    m=r.nextInt(n);//random element between  0 and  n
    if (t[m]==1){
        //I have problems with this. I want in case of duplication element
        //occurs repeat this steps afain until there will be different number.
    else{
        t[m]=1;
        x[i]=m;
    }
}

So I fill concret my problem: if t[m]==1. It means that this element occurs already so I want to generate a new number, but problem is that number of generated numbers will not be k because if i==0 and occurs duplicate element and we write continue then it will switch at i==1. I need like goto for the repeat step. Or:

for (int i=0;i<x.length;i++){
    loop:
        m=r.nextInt(n);

    if ( x[m]==1){
        continue loop;
    }
    else{
        x[m]=1;
        a[i]=m;
        continue; //Continue next step at i=1 and so on.
    }
}

I need this code in Java.

A: 
Create an array arr with n elements (1..n);
for i=1 to k {
  result[i] = arr[rand]
  delete arr[result[1]]
}
Mark Baker
This solution is O(k*n), when it could have been O(k) only. By replacing your "delete" step with an item swap, you can improve it to O(n), but this is still not optimal.
Eyal Schneider
What language is this?
Kevin Bourrillion
pseudocode, though I was thinking a PHP solution. Hadn't noticed the OP was talking java
Mark Baker
Though for a strict PHP solution, I'd have shuffled arr and then sliced out the first k entries
Mark Baker
+2  A: 

It seems that you need a random sampling algorithm. You want to be able to choose m random items from the set {0,1,2,3...,n-1}.

See this post, where I wrote about 5 efficient algorithms for random sampling.

Following is Floyd's implementation, which can be useful in your case:

private static Random rnd = new Random();
...
public static Set<Integer> randomSample(int n, int m){
    HashSet<Integer> res = new HashSet<Integer>(m);
    for(int i = n - m; i < n; i++){
        int item = rnd.nextInt(i + 1);
        if (res.contains(item))
            res.add(i);
        else
            res.add(item); 
    }
    return res;
} 
Eyal Schneider
You might want to reference 'Reservoir sampling' from the linked post
Will
@Will: Thanks, actually the last algorithm in my blog post is exactly this one. However, I was not aware of its common name. I will fix it.
Eyal Schneider