我尝试使用3路分区技术实现快速排序算法,使用" m1"和" m2"作为索引来分隔元素等于枢轴的区域。 这是我的代码:
public class Sorting {
private static Random random = new Random();
private static int[] partition3(long[] a, int l, int r) {
long x = a[l];
int m1 = l;
int m2 = l;
for (int i = l + 1; i <= r; i++) {
if (a[i] < x) {
m1++;
m2++;
swap(a, m1, m2);
}
if (a[i] == x) {
m2++;
swap(a, i, m1);
}
}
swap(a, l, m1);
int[] m = {m1, m2};
return m;
}
private static void swap(long[] a, int i, int j) {
long temp = a[i];
a[i] = a[j];
a[j] = temp;
}
private static void randomizedQuickSort(long[] a, int l, int r) {
if (l >= r) {
return;
}
int k = random.nextInt(r - l + 1) + l;
long t = a[l];
a[l] = a[k];
a[k] = t;
int m[] = partition3(a, l, r);
randomizedQuickSort(a, l, m[0] - 1);
randomizedQuickSort(a, m[1] + 1, r);
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
long[] a = new long[n];
for (int i = 0; i < n; i++) {
a[i] = scanner.nextLong();
}
randomizedQuickSort(a, 0, n - 1);
for (int i = 0; i < n; i++) {
System.out.print(a[i] + " ");
}
}
}
大多数情况下,它会为我的测试输出正确的答案,但有时并没有。谁能告诉我我做错了什么?
答案 0 :(得分:0)
当您在列表中重复数字时,您的代码会失败。例如,您的代码未通过测试用例:
1 2 1 3 1
由于随机数生成,它每次都会返回不同的内容,但它不会成为正确的答案。这是您的partition3()
函数的问题,特别是for循环中的情况,您可以在其中决定增量和翻转的位置。在这种情况下:
if (a[i] < x) {
m1++;
m2++;
swap(a, m1, m2);
}
您错过了将第i个索引移动到正确位置的交换。交换看起来像这样:
if (a[i] < x) {
m1++;
m2++;
swap(a, m1, m2);
swap(a, m1, i); //The missing swap.
}
在你的其他条件中,你错过了两件事。首先,它应该是一个else-if,以避免意外进入两个if条件。其次,你在错误的位置交换。您应该在m2(第二个墙)处交换,而不是在m1处交换。这是因为第二个墙处理与枢轴相同的值,而不是第一个。更正了,你的第二个if条件看起来是这样的:
else if (a[i] == x) { //Note the addition of the else
m2++;
swap(a, i, m2); //Corrected, now swaps at m2
}
通过这些更正,您的代码似乎可以按预期工作。
答案 1 :(得分:0)
如果&#34; m1&#34;它会更容易和&#34; m2&#34; (等于&#39;区域的两个分隔符)从相对的边开始。如果元素小于数据透视表,则使用左边界定符进行交换,如果大于数据透视表,则使用右边界定符进行交换。否则,如果它相等,我们只需移动&#34; i&#34;指数。它会是这样的:
private static int[] partition3(long[] a, int l, int r) {
long x = a[l];
int m1 = l;
int m2 = r;
int i = l + 1;
while(i <= m2) {
if (a[i] > x) {
swap(a, i, m2);
m2--;
} else if (a[i] < x) {
swap(a, m1, i);
m1++;
i++;
} else {
i++;
}
}
int[] m = {m1, m2};
return m;
}