二分查找:在已排序数组A中,定义左边界l和右边界r,获取中间索引m=floor(l+r)/2,然后将中间索引的值a[m]与待搜索值进行比较,相等则找到,返回中间索引,a[m]>t,右侧全都大于t,m-1设置为右边界重新查找,a[m]<t,m+1设为左边界重新查找。一般奇数二分取中间,偶数二分取中间靠左。一般而言,对于包n含个元素的列表,用二分查找最多需要log以2为底的n次方步,用简单查找最多需要 n 步,例如有128个元素,则计算器中log10(128)/log10(2),整数则为最终结果,小数则舍去小数部分再加一
排序:目标:掌握常见排序算法(快跑,冒泡,选择,插入等)的实现思路,手写冒泡快排的代码,了解各个排序算法的特性如时间复杂度,稳定性。
冒泡排序:
升序:依次比较数组中相邻两元素的大小,若a[j]>a[j+1],则交换两元素,两两都比较一遍称为一轮冒泡,结果是最大的元素排至最后。然后重复直至整个数组有序。(从头开始,两个相邻的开始比较,把大的一直往右边移直到小于相邻右边的,然后再从头开始)。优化方法:每轮冒泡时最后一次交换索引可作为下一轮冒泡的比较次数,如果值为零则表示整个数组有序,直接退出外层循环。
选择排序:
升序:将数组分为两个子集,排序的和未排序的,每一轮从未排序的子集中选出最小的元素放入排序子集,然后重复直至整个数组有序。优化:每一轮可以先找最小的索引,在每轮最后再交换元素。
与冒泡排序相比,二者平均时间复杂度都是O(n2),选择排序一般快于冒泡排序,因为交换次数小,但是集合有序度高的情况下冒泡优于选择,冒泡属于稳定排序算法,选择属于不稳定排序算法,因为选择排序在相同元素多次排序时可能会打乱相同元素原本的顺序
插入排序:
升序:将数组分为两个区域,排序区域和未排序区域,每一轮从未排序区域中取出第一个元素插入到排序区域(需要保证顺序)重复直至有序。优化:待插入元素进行比较时,遇到比自己小的元素,就代表找到了插入位置,无需进行后续比较,插入时可以直接移动元素,而不是交换元素。
与选择排序相比,时间复杂度都是O(n2),大部分情况下插入优于选择,有序集合插入的时间复杂度为O(n),属于稳定排序算法
希尔排序:先以4为步长进行一个排序,然后2为步长排序,最后以1为步长进行排序,能减小排序次数
快速排序:每一轮排序选择一个基准点(pivot)进行分区,小于基准点的进入一个分区,大于的放入另一个分区,完成分区时基点元素的位置就是其最终位置,然后再子分区重复以上过程,直至子分区元素个数小于等于1,(体现了分而治之的思想divide-and-conquer,d&c)
单边循环快排:lomuto洛穆托分区方案:
1、 选择最右侧元素作为基准点元素
2、 J指针负责找到比基准点小的元素,一旦找到与i交换
3、 I指针维护小于基准点元素的边界,也是每次交换的目标索引
4、 最后基准点与i交换,i即分区位置
双边循环快排:并不完全等价于hoare霍尔分区方案
1、 选择最左元素作为基准点元素
2、 J指针负责从右向左找比基准点小的元素,i指针负责从左向右找比基准点大的元素,一旦找到二者交换,直到i,j相交
3、 最后基准点与i(此时i与j相等)交换,i即为分区位置