归并排序

归并排序

** 写在前面的话: 归并排序的时间复杂度为O(N*logN),额外空间复杂度为O(N)**.

什么是归并排序呢?

  • 一点点专业叫法: 迭代就理解为递归,分治就理解为一分为二的过程.
  • 举例:以[2,5,7,1,6,4]为例
    • 首先将其一分为二,划分成两个部分,分别为[2,5,7][1,6,4].
    • 然后分别对左右两部分进行排序,得到[2,5,7][1,4,6].
    • 申请一个辅助数组,长度和原来的数组相同.
    • 左右两个部分分别从左到右进行比较,谁小就放到辅助数组中去,例如此例中,执行顺序是这样的
      1. 21比较,2大,就把1放在辅助空间中,然后左边数组下标不动,右边下标+1.
      2. 24比较,4大,就把2放进辅助空间,然后左边数组下标+1,右边数组下标不变.
      3. …以此类推,当一个到了末尾之后,比较停止,剩下的直接全部放到辅助数组中.
      4. 最后得到有序数组[1,2,4,5,6,7],再将其复制回原数组即可.

分析其时间复杂度

* 这是一个递归的过程,我们可以用`master公式(): T(N) = a * T(N / b) + O(N^d)`来套一下.
* 假设数组样本量为`N`,划分成了两部分,所以两边的样本量是`(N/2)`,有因为有两部分,所以为`2*T(N/2)`.
* 额外空间复杂度为`O(N)`,因为要申请一个长度为N的辅助数组.
* 用`master`公式套,可得`T(N) = 2 * T(N / 2) + O(N)`,即`a=2,b=2,d=1`.
* 由此可知,`(log(b,a)) => 1`,而`d == 1`,所以可得归并排序的时间复杂度为***`O(N^d * logN) == O(N*log(N))`***.
* 对于额外空间复杂度,就把它当作只生成了一个最大的数组(就是初始化数组的长度),不考虑中间的就好了,所以是`O(N)`.

代码:

  • 行数有点多,我就直接放github上了,需要的话就自己看下: 归并排序

举例:

  1. 小和问题(以[1,3,4,2,5]为例)

    1. 什么是小和问题: 就是在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和,求一个数组的小和的和.
    2. 分析:
      1. 1左边比1小的数: 没得.
      2. 3左边比3小的数: 1.
      3. 4左边比4小的数: 1,3.
      4. 2左边比2小的数: 1.
      5. 5左边比5小的数: 1,3,4,2.
      6. 所以总的小和为:1+1+3+1+1+3+4+2 = 16.
    3. 解决办法
      1. 每个数都遍历一下左边,小的数就相加,其时间复杂度为O(N^2),我们对数器就可以这么写.
      2. 用归并思想,产生小和就在合并过程中产生,但是其中有一个要注意的点:
        1. 在合并的时候,假如左边为[1,3,4],右边为[2,5].
        2. 12进行比较,发现2 > 1,***而此时,2右边包含2本身一共有两个元素,所以此时需要将1×2***,然后在将右边的1放到辅助数组中.
        3. 再将32比较,发现3 > 2,此时不产生小和,直接将2放入辅助数组.
        4. …以此类推.
        5. 其实就是,合并的时候左边比右边大,就产生小和,左边比右边小就不产生小和,同时要注意右边的数比左边大的时候,要看右边较大的这个数的右边还有几个数,此时左边较小的数就要乘以几.
        6. 时间复杂度和归并排序一致,为O(N*log(N)).
    4. 代码超链接: 小和问题代码.
  2. 逆序对问题(以[1,3,4,2,5]为例)

    1. 逆序对就是指在一个数组中,左边的数比右边的数大,则这两个数构成一个逆序对,请打印所有的逆序对.
    2. 思路与小和问题相同,我就不多赘述了哈,就是在归并重组的时候找出逆序对,放在一个list中返回就可以了.
    3. 直接来代码吧哈哈.逆序对问题代码.
  3. 偶然发现的一个牛客剑指offer上的题目,就是一个归并的题目.

    1. 题目地址: 逆序对问题, 我的代码上面也有哈哈哈,大家可以参考,就是一个归并,不过多了一个取模操作而已.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值