My problem is the following: I need to shuffle an array and then get just the first N elements.
I am currently shuffling the whole array, that has 50+ elements, but this gives me performance problems, since the shuffling routine is called 1e+9 times.
I am currently implementing the Fisher-Yates algorithm to shuffle:
public static void shuffle(int[] array) {
Random gen = new Random();
for (int i = array.length - 1; i > 0; i--) {
int index = gen.nextInt(i + 1);
int a = array[index];
array[index] = array[i];
array[i] = a;
}
}
Then I select just the first N elements.
I have also tried using Reservoir sampling, but it just saved me 1 second. That's not enough, since my program runs for 30 secs. Also, I might have implemented it incorrectly, because I am not getting the same results when compared to the Fisher-Yates algorithm. This is my implementation:
public static int[] shuffle(int[] array, int N) {
int[] ret = new int[N];
for (int i = 0; i < N; i++) {
ret[i] = array[i];
}
Random gen = new Random();
int j;
for (int i = N; i < array.length; i++) {
j = gen.nextInt(i+1);
if (j <= N - 1)
ret[j] = array[i];
}
return ret;
}
To conclude, what I need is a a shuffling algorithm that would pick N random elements using a search of length N, instead 50+. If not possible, something better then Fisher-Yates and Reservoir sampling.
Note-1: Altering the original "int[] array" is not a problem.
Note-2: N is usually around 10.