左神算法课程笔记
一.认识O(NlogN)的排序
①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳
master公式
T [n] = aT[n/b] + T (N^d)
a:子问题个数
b:每次递归是原来1/b的规模
d:除去子问题,剩下的规模
解法:
①当d<logb a时,时间复杂度为O(n^(logb a))
②当d=logb a时,时间复杂度为O((n^d)*logn)
③当d>logb a时,时间复杂度为O(n^d)
1.归并排序
①平分两份,左边排好序,右边排好序;
②新开一个辅助空间help,大小为,R-L+1;
③分别从1,M+1开始,较小值放入help;
2T[n/2]+T(N^1) --> d=logb a
O(N*logN) 额外空间:O(N)
2.小和问题
在一个数组中,每一个数左边比当前数小的数累加起来,叫做这个数组的小和。求一个数组的小和。
可以看作有n个数>x,就有n个x加在结果res里
还是结合归并排序
①平分两份,左边排好序,右边排好序;
②新开一个辅助空间help,大小为,R-L+1;
③分别从1,M+1开始比较
左边较小,res+=右边个数*左边数值,左边数值加入help辅助空间
右边较小,直接加入辅助空间
当左右相等,先放入右边数值进help(如果先放左边进help就不知道右边有多少个数大于它)
④ans=左边小和+右边小和+merge在一起后的小和
3.荷兰国旗问题1
给定一个数组arr,和一个数num,请把小于等于num的数放在数组的左边,大于num的数放在数组的右边。要求额外空间复杂度0(1),时间复杂度0(N)
①arr[i]<num
arr[i]和小于区的下一个交换,指针L++
②arr[i]>num
arr[i]不动,i++(继续向下判断)
4.荷兰国旗问题2
给定一个数组arr,和一个数num,请把小于num的数放在数组的左边,等于num的数放在数组的中间,大于num的数放在数组的右边。要求额外空间复杂度0(1),时间复杂度o(N)
①arr[i]<num
arr[i]和小于区的下一个交换,指针i++
②arr[i]=num
arr[i]不动,i++(继续向下判断)
③arr[i]>num
arr[i]和大于区前一个交换,i不动
5.快排1.0
①最后一个数m做基准
②arr[i]>m,放左边
arr[i]<m,放右边
③大于m区的第一个数与m做交换
④重复上述三步骤
空间复杂度O(N)
6.快排2.0
①最后一个数m做基准
②arr[i]>m,放左边
arr[i]=m,放中间
arr[i]<m,放右边
③大于m区的第一个数与m做交换
④等于m区域就不动,左右两区域继续重复上述三步骤(每次都会处理好一批数)
空间复杂度O(N)
7.快排3.0
先随机选一个数作为划分值m
在进行快排2.0
空间复杂度O(N*logN)
二.详解桶排序及排序内容大总结
1.堆结构
把从0开始的数组,对应成一颗完全二叉树
0
1 2
3 4 5 6
i位置 父节点:( i - 1 ) / 2
左子树:2 * i + 1
右子树:2 * i + 2
大根堆,小根堆
heapInsert:(新增一数)
每加入一个新元素,与其父节点作比较,若大于等于,则交换
继续与交换后位置的父节点作比较,直到不大于或来到0位置
heapify:(返回并删除最大元素)
判断有无孩子
如果 较大的孩子 比 此元素 大 则做交换
不大于则退出循环
heapSort:(堆排序)
先做成大根堆
然后把0位置上的最大值与heapSize位置的最小值交换
heapSize减少1
重复此操作
时间复杂度O(NlogN) 空间复杂度O(1)(只开辟了有限的几个变量)
2.系统默认小根堆
PeiorutyQueue<Integer> heap=new PriorityQueue<>();
3.对数器
Arrays.sort(arr,new Comparator())
punlic void class AComp implements Comparator<Integer>{
//返回负数的时候,第一个参数排在前面
//返回正数的时候,第二个参数排在前面
//返回0的时候,谁在前无所谓
@Override
public int compare( Student 01, Student o2){
return o1.age-o2.age;
}
}
比较器运用在特殊标准的排序上
4.桶排序
①统计数字中最大数有几位(如1228,千位)
②把所有比千位小的数,前面补0
③所有出现过的数字,从0到9,每个出现过的数字当做一个桶
④从个位开始,个位为0放在0号桶,以此类推
⑤把刚才放入桶内的所有数,从左往右倒出(同一桶内,先进先倒出)
⑥个位,十位,百位,千位。。。重复此过程,得到最终排序好的结果