2.O(NlogN)的排序算法
- 1.递归
- 递归行为
- 压栈,
- 压栈结束之后的操作可以看成树的后根遍历
- 递归时间复杂度估计
- master公式:T(N)=a*T(N/b)+O(N^d)
- T(N):母问题
- a*T(N/b):子问题(需要规模均分)
- O(N^d):附加操作
- 使用
- master公式:T(N)=a*T(N/b)+O(N^d)
- 递归行为
-
-
- 例子:
- T(N)=2*T(N/2)+O(1),由参数关系得到时间复杂度为O(N)
- 例子:
-
-
- 小技巧(除以二变右移一位)
- 数字除以二可以写成向右移一位(速度更快)
- 如(R-L)/2可以写成(R-L)>>1
- 小技巧(除以二变右移一位)
- 2.归并排序mergesort
- 归并排序
- 概念
- 创建在归并操作上的一种有效的排序算法。算法是采用分治法(Divide and Conquer)的一个非常典型的应用,且各层分治递归可以同时进行。归并排序思路简单,速度仅次于快速排序,为稳定排序算法,一般用于对总体无序,但是各子项相对有序的数列。
- 1. 基本思想
- 归并排序是用分治思想,分治模式在每一层递归上有三个步骤:
- 分解(Divide):将n个元素分成个含n/2个元素的子序列。
- 解决(Conquer):用合并排序法对两个子序列递归的排序。
- 合并(Combine):合并两个已排序的子序列已得到排序结果。
- 2. 实现逻辑
- 2.1 迭代法
- ① 申请空间,使其大小为两个已经排序序列之和,该空间用来存放合并后的序列
- ② 设定两个指针,最初位置分别为两个已经排序序列的起始位置
- ③ 比较两个指针所指向的元素,选择相对小的元素放入到合并空间,并移动指针到下一位置
- ④ 重复步骤③直到某一指针到达序列尾
- ⑤ 将另一序列剩下的所有元素直接复制到合并序列尾
- 2.2 递归法
- ① 将序列每相邻两个数字进行归并操作,形成floor(n/2)个序列,排序后每个序列包含两个元素
- ② 将上述序列再次归并,形成floor(n/4)个序列,每个序列包含四个元素
- ③ 重复步骤②,直到所有元素排序完毕
- 2.1 迭代法
- 代码
- 递归法:
- T(N)=2T(N/2)+O(N)
- master公式:O(N*logN)
- 递归法:
- 概念
- 归并排序
-
- 复杂度
- 时间复杂度:O(NlogN)
- 时间复杂度变小的原因:前面的比较信息没有被浪费,变成了有序的东西在后面利用了,所以时间复杂度减少了
- 额外空间复杂度:O(N)
- 时间复杂度:O(NlogN)
- 实际问题
- 小和问题
- 问题:
- 小和问题
- 复杂度
-
-
-
- 算法:
- 每次归并过程中得到右边部分数组中大于左边某个数字的个数,从而确定该左边数字在和右边部分数字比较从而在小和计算中出现的次数
- 右边数字小于等于左边数字时,先将右边归并到额外位置中
- 当右边数字大于左边数字时,直接通过右边数组中大于右边数字的个数得到左边数字的小和个数
- 合并过程中只产生左边部分数组的数字的小和
- 小和个数=左边部分数组小和个数+右边部分数组小和个数+合并过程中判断出的小和个数
- 代码:
- 算法:
-
-
-
-
- 逆序对问题
- 问题:
- 逆序对问题
-
- 3.快速排序
- 快排1
- 选择最后一个数字将其余数据分为左边小于等于该数字的部分和右边大于该数字的部分
- 将该数字放在两部分数据中间
- 对左边部分数据和右边部分数据分别递归该操作
- 时间复杂度为O(N²)
- 快排2(利用荷兰国旗问题)
- 选择最后一个数字将其余数据分为左边小于该数字的部分、中间等于该数字的部分和右边大于该数字的部分
- 将该数字放在中间的数据部分
- 对左边部分数据和右边部分数据分别递归该操作
- 时间复杂度为O(N²)
- 快排3
- 随机选择一个数字放到最后,将其余数据分为左边小于该数字的部分、中间等于该数字的部分和右边大于该数字的部分
- 将该数字放在中间的数据部分
- 对左边部分数据和右边部分数据分别递归该操作
- 时间复杂度为O(NlogN)(由概率求得的期望)
- 代码:
- 快排1
-
- 时间复杂度:
- 最差(划分值很偏):O(N²)
- 最好(划分值在差不多中间的位置):
- T(N)=2T(N/2)+O(N)
- 由master公式可以得到时间复杂度为O(NlogN)
- 荷兰国旗问题:
- 问题1:
- 问题:
- 问题1:
- 时间复杂度:
-
-
-
- 算法:
- 一个指针从左向右依次移动,并和
- 算法:
- 问题1:
- 问题:
-
-
-
-
-
- 算法:
- 1.[i]<num,[i]和小于区的下一个交换,小于区右移,i++
- 2.[i]==num,i++
- 3.[i]>num,[i]和大于区的前一个交换,大于区左移,i原地不变
- 算法:
-
-