排序算法解析

选择排序

定义: N个数排序,第一次在0~N-1个数中找出最小值,与0位置的数进行交换
第二次在1~N-1个数中找出最小值,与0位置的数进行交换,以此类推
解析:时间复杂度是O(N2)

冒泡排序

定义:N个数排序,从第0个数开始依次与下一个数做比较,较大的数放在右边
解析:时间复杂度是O(N2 )

插入排序

定义:N个数排序,保证0~0位置上有序,
保证0~1位置上有序,以此类推
解析:无序部分的数,以此与无序部分的数进行比较,当比自己数小时,进行交换,当第一次出现不比自己数大时停止交换

二分法

定义::通过每次砍半来确定数字是否存在

局部最小值问题

定义:一组相邻两个数都不相等的数,是否存在一个数比它左右两边的两个数都小的情况
分析:1.判断0位置和N-1位置是否是局部最小
2.用二分法进行判断中点是否是局部最小
3.如果中点小于中点左边一个的数,则从0~中点-1中找局部最小
4.如果中点大于中点右边一个的数,则从中点~N-2中找局部最小

小和问题

定义:记录一组数中,每一个在自己左边比自己小的数的总和。
分析:用归并排序,将这组数分为两部分,分别将左右两组数进行排序,先得到小和再排序

逆序对问题

定义:一组数中以每一个数为视角,右边数比自己的数大,就组成了一个逆序对
分析:用归并排序,从右往左进行依次的排序,先取逆序对,再排序

BiggerThanRightTwice

定义:对于每一个数来讲,大于右边的数的两倍
分析:用归并排序,从左往右进行依次排序,当左边部分的一个数小于右边数*2时右边的数停止遍历,并记录当前数到前面数的个数

区间和的个数

定义:给定一个数组arr,两个整数lower和upper,返回arr中有多少个子数组的累加和在[lower,upper]范围上
分析:1.建一个新数组,数组中存放数组的前缀和
2.求以x截止的子数组是否满足前缀和在[lower,upper]之间,就是求在[0,x-1]之间是否满足前缀和在
[x-upper,x-lower]
3.用归并排序,在合并时,创建两个变量划分为符合要求的子数组,然后将左边的总数,右边的总数
和归并的总数加在一起

Partition过程

定义:给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。
分析:两种情况:1.当前数小于等于num,交换≤区边界的下一个数与当前数的位置,边界+1,指针+1
2.当前数大于num,指针+1

归并排序

定义:按照先左右各自排序,再merge的排序方法
分析: 将数分为两部分,求出中点,将左边/右边的数分别递归,然后merge
新增help数组,将左右指针分别指向左右的,最小端
1.如果左右两边都没有超出边界,那么将max(左指针,右指针)存入help数组中
2.右边界超了,将左边界剩下的值分别存入help中
3.左边界超了,将右边界剩下的值分别存入help中

快排进阶

定义:一个数组的最后一个数为p,将数组排列成三个区p区,不用排序
分析:划分为两个区域,小于区和大于区,1.当前数小于p,交换小于区边界的下一个数与当前数的位置,边界+1,指针+1
2.当前数大于p,交互大于区边界的上一个数与当前数的位置,边界+1,指针不变
3.最后一个数,在排序完成后,与大于区第一个数交换

一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数

解析:1.Eor为数组每一个数异或的结果,结果必为 a^b
2.c为Eor最右侧的1的数
3.Eor’为所有满足&c=1的数的异或
4.a就为Eor’,b为Eor’^Eor

一个数组中有一种数出现K次,其他数都出现了M次,M > 1, K < M,找出出现k次的数

解析:1.用一个32长度的int数组将数组中每一个数出现在每一位的次数做统计
2.对int数组进行遍历,余M不等于0的,在一个int变量中进行记录,最终会返回这个数

桶排序

思想下的排序:计数排序 & 基数排序

1)桶排序思想下的排序都是不基于比较的排序

2)时间复杂度为O(N),额外空间负载度O(M)

3)应用范围有限,需要样本的数据状况满足桶的划分

计数排序和基数排序

1)一般来讲,计数排序要求,样本是整数,且范围比较窄

2)一般来讲,基数排序要求,样本是10进制的正整数

一旦要求稍有升级,改写代价增加是显而易见的
解析:找出基数中高位最多的数,并记录位数,依次,遍历低位到高位,每一位都将数依次放入对应的位数对应的0-9的桶内,并组成一个help数组,help数组为新数组再继续进行桶排序操作

10桶合1桶的方法:将每一个数的当前位进行求前缀合,条件为<=0,1,2,3,4…的数

排序算法总结

                  时间复杂度	额外空间复杂度		稳定性

选择排序 O(N^2) O(1) 无
冒泡排序 O(N^2) O(1) 有
插入排序 O(N^2) O(1) 有
归并排序 O(NlogN) O(N) 有
随机快排 O(N
logN) O(logN) 无
堆排序 O(N*logN) O(1) 无

计数排序 O(N) O(M) 有
基数排序 O(N) O(N) 有

1)不基于比较的排序,对样本数据有严格要求,不易改写
2)基于比较的排序,只要规定好两个样本怎么比大小就可以直接复用
3)基于比较的排序,时间复杂度的极限是O(NlogN)
4)时间复杂度O(N
logN)、额外空间复杂度低于O(N)、且稳定的基于比较的排序是不存在的。
5)为了绝对的速度选快排、为了省空间选堆排、为了稳定性选归并

常见的坑

1)归并排序的额外空间复杂度可以变成O(1),“归并排序 内部缓存法”,但是将变得不再稳定。

2)“原地归并排序" 是垃圾贴,会让时间复杂度变成O(N^2)

3)快速排序稳定性改进,“01 stable sort”,但是会对样本数据要求更多。

工程上对排序的改进

1)稳定性的考虑

2)充分利用O(N*logN)和O(N^2)排序各自的优势

你可能感兴趣的:(算法)