You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java快速排序代码部分测试用例超时,请求排查错误原因

快速排序处理长数组超时问题排查

我的Java快速排序代码在短数组(如{3,2,1}、{3,7,4,2,1,9})测试中运行正常,但处理40或100个元素的测试用例时出现超时。代码实现了自定义分区算法,随机选取基准值并避开选中最小值的情况,随后对左右子数组递归排序,求代码中的错误原因。

import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int[] A = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = in.nextInt();
        }
        QuickSort(A, 0, N - 1);
        for (int j = 0; j < N; j++){
            System.out.print(A[j] + " ");
        }
    }

    public static int Partition(int[] A, int l, int r) {
        int x = (int)(Math.random() * (r - l + 1) + l);
        int Z = A[l];
        for (int i = l; i <= r; i++) {
            if (A[i] < Z) {
                Z = A[i];
            }
        }
        while (A[x] == Z) {
            x = (int)(Math.random() * (r - l + 1) + l);
        }
        int C = l - 1;
        for (int i = l; i <= r; i++) {
            int y = A[i];
            if (y >= A[x]) {
                continue;
            }
            if (y < A[x]) {
                int fake = A[C+1];
                A[C+1] = A[i];
                A[i] = fake;
                ++C;
            }
        }
        return C + 1;
    }
    public static int[] QuickSort(int[] A, int l, int r){
        if (r - l + 1 <= 1) {
            return A;
        }
        if (l < r) {
            int Index = Partition(A, l, r);
            QuickSort(A, l,  Index - 1);
            QuickSort(A, Index, r);
        }
        return A;
    }
}

错误原因分析

1. 递归边界引发无限递归

QuickSort方法中的递归调用为:

QuickSort(A, l,  Index - 1);
QuickSort(A, Index, r);

当Partition返回的Index等于l时,第二个递归调用的范围还是[l, r],与原调用范围完全一致,会直接陷入无限递归,这是超时的核心原因。比如当分区后所有元素都大于等于基准值时,C会保持l-1,返回C+1 = l,此时第二次递归永远处理原区间,无法终止。

2. 最小值判断逻辑存在死循环风险

Partition中先遍历找到最小值Z,再循环随机选取基准直到选中的元素不是最小值。但如果数组中所有元素都是最小值(如{2,2,2,...}),while (A[x] == Z)会永远成立,程序直接死循环,无法继续执行。

3. 基准值未归位,分区逻辑不完整

标准快速排序会将基准值交换到分区后的正确位置(即C+1的位置),但你的代码中基准值A[x]始终留在原位置。这意味着分区后的数组并没有真正以基准值为分割点,递归处理时会重复处理基准值,大幅降低效率,甚至触发无限递归。

4. 冗余条件判断增加不必要开销

分区中的两个条件if (y >= A[x])和if (y < A[x])是互斥的,完全可以合并为一个判断,冗余代码虽不直接导致超时,但会增加额外计算开销。

修正后的代码示例

import java.util.Scanner;
import java.util.Random;

public class Main {
    private static final Random random = new Random();

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int N = in.nextInt();
        int[] A = new int[N];
        for (int i = 0; i < N; i++) {
            A[i] = in.nextInt();
        }
        quickSort(A, 0, N - 1);
        for (int num : A) {
            System.out.print(num + " ");
        }
    }

    public static int partition(int[] A, int l, int r) {
        // 随机选取基准索引
        int pivotIdx = l + random.nextInt(r - l + 1);
        // 将基准值交换到右端,方便统一处理
        swap(A, pivotIdx, r);
        int pivot = A[r];
        int C = l - 1;

        // 遍历数组,将小于基准的元素移到左侧
        for (int i = l; i < r; i++) {
            if (A[i] < pivot) {
                C++;
                swap(A, C, i);
            }
        }
        // 将基准值放到正确的分割位置
        swap(A, C + 1, r);
        return C + 1;
    }

    public static void quickSort(int[] A, int l, int r) {
        if (l >= r) {
            return;
        }
        int pivotPos = partition(A, l, r);
        // 递归处理左右子数组,避开已归位的基准值
        quickSort(A, l, pivotPos - 1);
        quickSort(A, pivotPos + 1, r);
    }

    private static void swap(int[] A, int i, int j) {
        int temp = A[i];
        A[i] = A[j];
        A[j] = temp;
    }
}

内容的提问来源于stack exchange,提问作者Форс

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 16:53:20