我試圖實現以下僞代碼。我只需要使用邏輯分區來做到這一點。查找未排序數組中的第k個最小元素
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);
}
}
這是我在它的企圖到目前爲止:
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;
}
我select
方法不返回實際的第k個最小元素。分區方法只在小於m的元素上正常工作。在m右側的數組部分,有任何值的元素。我該如何解決?我在網上看到的所有解決方案都與我的方法相同。任何幫助表示讚賞!
我很困惑。在僞代碼中它說什麼關於重新排序數組?因爲如果你要重新排序,你可以使用排序算法,然後返回數組的第k個元素... – Mark
該算法應該比完整排序更快。你必須以某種方式表示S1,S2和S3,通過重新排序數組並不是最難的事情。 –
您需要學習使用調試器。 –