【算法总结】归并排序及双指针

本文深入探讨了归并排序的分治思想与实现细节。通过递归分解数组,将问题规模不断减小,然后利用双指针算法将两个有序子数组合并成一个有序数组。归并排序的时间复杂度为O(nlogn),空间复杂度为O(n)。在实际操作中,重点在于理解分治策略以及如何有效地合并两个有序序列。
摘要由CSDN通过智能技术生成

1. 归并排序——分治

# 算法原理

归并排序的思想就是分治,先递归分解数组,再合并数组。

将数组分解到最小之后,再往上一层两两合并两个有序的数组,最终递归返回的就是一个排好序的数组。

递归分解的时间复杂度是O(logn),合并数组的时间复杂度是O(n),因此归并排序的时间复杂度就是O(nlogn)

# 步骤

  1. 确定分界点
    • mid = (l + r) / 2
  2. 递归调用左右区间
    • 一层层调用到底,从最底层归并
  3. 归并排序, 合二为一
# 如何实现合二为一?

合并的基本思路就是双指针算法,比较两个数组最前面的数字,谁小就先取谁,取了后相应的指针就往后移动一位。 然后再比较,直到一个数组为空,最后把一个数组的剩余部分复制过来即可。

image-20220410162713563

  1. 找两个指针中较小的一个数,把值写入res[],然后指针右移
  2. 直到其中一个序列的指针指向最后一个
  3. 把另一个序列的指针剩下的数依次写入res[]

# 代码模板

const int N = 10e5 + 10;
int temp[N];
void merge_sort(int q[], int l, int r)
{
    if(l >= r) return;
    int mid = (l + r) >> 1;
    merge_sort(q, l, mid);
    merge_sort(q, mid + 1, r);
    int i = l, j = mid + 1, k = 0;
    while(i <= mid && j <= r) {
        if( q[i] <= q[j] ) temp[k++] = q[i++];
        else temp[k++] = q[j++];
    }
    while(i <= mid) temp[k++] = q[i++];
    while(j <= r) temp[k++] = q[j++];
    for(i = l, j = 0; i <= r; i++, j++) q[i] = temp[j];
}

# 总结

归并排序没有太多复杂的边界问题,核心思想是分治,只要理解了这一点,基本上原理就弄清楚了。

在进行归并排序之前,先递归调用左右区间,可以理解为将数组二分分解。

调用到最深一层也就是区间里只有一个元素的时候,开始执行递归函数的返回,也就是执行归并的过程。

归并的过程可以如上图所示,每一层的都是把2个相邻的区间通过双指针算法排序并合并到一个区间(合并这个动作由递归返回发生),每次递归返回时区间都是有序的,最终合并回一个区间,完成排序。

需要注意的是,归并排序的时间复杂度是O(nlogn),但是中间过程需要用到一个数组来存放临时排序的结果,所以空间复杂度是O(n)。

2022.4.10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值