I'm trying to implement the following pseudocode. I need to do this using logical partitions only.
Procedure SELECT( k,S)
{ if |S| =1 then return the single element in S
else { choose an element a randomly from S;
let S1,S2,and S3 be he sequences of elements in S
less than, equal to, and greater than m, respectively;
if |S1| >=k then return SELECT(k,S1)
else
if (|S1| + |S2| >=k then return m
else return SELECT(k-|S1|-|S2| , S3);
}
}
Here is my attempt at it so far:
public static int select(int k, int[] s, int arrayLeft, int arrayRight) {
if (s.length == 1) {
return s[0];
} else {
Random rand = new Random();
int right = rand.nextInt(arrayRight) + arrayLeft;
int m = s[right];
int pivot = partition(s, arrayLeft, right); // pivot = |s1|
if (pivot >= k) {
return select(k, s, arrayLeft, pivot - 1);
} else {
// Calculate |s2|
int s2Length = 0;
for (int i = pivot; s[i] == m; i++) {
s2Length++;
}
if (pivot + s2Length >= k) {
return m;
} else {
int s3Left = pivot + s2Length;
return select(k - pivot - s2Length, s, s3Left + 1, s.length);
}
}
}
}
// all elements smaller than m are to the left of it,
// all elements greater than m are to the right of it
private static int partition(int[] s, int left, int right) {
int m = s[right];
int i = left;
for (int j = left; j <= right - 1; j++) {
if (s[j] <= m) {
swap(s, i, j);
i++;
}
}
swap(s, i, right);
return i;
}
private static void swap(int[] s, int i, int j) {
int temp = s[i];
s[i] = s[j];
s[j] = temp;
}
My select
method isn't returning the actual kth smallest element. The partition method only does its job properly on the elements smaller than m. On the portion of the array to the right of m, there are elements of any value. How do I fix this? All of the solutions I've seen online appear the same as my method. Any help is appreciated!