O(n log n)算法:高效排序的奥秘

分治算法是一种通过将问题分解为若干个规模较小的相同问题来解决问题的方法。该算法首先将问题划分为若干个子问题,然后递归地解决这些子问题,并最终将子问题的解合并为原问题的解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章摘要

O(n log n)时间复杂度是算法效率的重要指标,表示每个元素需参与log n次分组或合并操作。典型应用包括归并排序、堆排序等分治算法。以排序1000本书为例,采用分治策略:先将书分成两半各自排序再合并,每本书都会经历约10(log₂1000≈10)次分组合并。归并排序代码展示了如何递归拆分数组并有序合并,其时间复杂度为n次操作乘以log n层分解。堆排序通过建堆和反复调整实现同样效率。这类算法比O(n²)快得多,是排序算法的效率天花板,适用于需要高效处理大规模数据的场景。


一、什么是 O(n log n)?

  • n:数据规模
  • log n:每次操作都能把问题“分成两半”,比如二分法
  • O(n log n):每个元素都要参与“分组”或“合并”log n次

常见场景:排序(归并排序、快速排序)、堆排序、某些高级数据结构的批量操作等。


二、生活化比喻

想象你有1000本书要按字母排序:

  • 你不会一口气全排好,而是先分成两堆,各自排好,再合并。
  • 每次分一半,分到最后每堆只剩一本书。
  • 然后一层层合并,每本书都要经历“分组”和“合并”log n次。

就像开运动会,先班级选拔,再年级选拔,最后全校决赛,每个人都要参加每一轮。


三、C#代码示例:归并排序(Merge Sort)

void MergeSort(int[] arr, int left, int right)
{
    if (left >= right) return;
    int mid = (left + right) / 2;
    MergeSort(arr, left, mid);         // 分左边
    MergeSort(arr, mid + 1, right);    // 分右边
    Merge(arr, left, mid, right);      // 合并
}

void Merge(int[] arr, int left, int mid, int right)
{
    int[] temp = new int[right - left + 1];
    int i = left, j = mid + 1, k = 0;
    while (i <= mid && j <= right)
    {
        if (arr[i] < arr[j])
            temp[k++] = arr[i++];
        else
            temp[k++] = arr[j++];
    }
    while (i <= mid) temp[k++] = arr[i++];
    while (j <= right) temp[k++] = arr[j++];
    for (int t = 0; t < temp.Length; t++)
        arr[left + t] = temp[t];
}

时间复杂度分析

  • 分组次数:每次分一半,分到只剩一个元素,总共 log n 层。
  • 每层操作量:每层都要把所有元素“合并”一遍,总共 n 次。
  • 总操作量:n * log n

四、再举一个例子:堆排序(Heap Sort)

void HeapSort(int[] arr)
{
    int n = arr.Length;
    // 建堆
    for (int i = n / 2 - 1; i >= 0; i--)
        Heapify(arr, n, i);
    // 取出堆顶元素,重建堆
    for (int i = n - 1; i > 0; i--)
    {
        int temp = arr[0];
        arr[0] = arr[i];
        arr[i] = temp;
        Heapify(arr, i, 0);
    }
}

void Heapify(int[] arr, int n, int i)
{
    int largest = i;
    int l = 2 * i + 1;
    int r = 2 * i + 2;
    if (l < n && arr[l] > arr[largest]) largest = l;
    if (r < n && arr[r] > arr[largest]) largest = r;
    if (largest != i)
    {
        int swap = arr[i];
        arr[i] = arr[largest];
        arr[largest] = swap;
        Heapify(arr, n, largest);
    }
}

时间复杂度分析

  • 建堆 O(n)
  • 每次取出堆顶并重建堆 O(log n),共 n 次
  • 总体 O(n log n)

五、总结口诀

  • O(n log n) = 每个人都要参加 log n 轮比赛
  • 排序算法的“天花板”:比 O(n²) 快得多,但比 O(n) 慢

六、常见O(n log n)算法

  • 归并排序(Merge Sort)
  • 堆排序(Heap Sort)
  • 快速排序(Quick Sort,平均O(n log n))
  • 平衡树/线段树/树状数组的批量操作

七、生活场景再补充

  • 分组比赛:每个人都要打每一轮,轮数是 log n
  • 分治法:每次分一半,分到最小再合并

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你一身傲骨怎能输

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值