递归算法复杂度分析步骤,递归算法的时间复杂度和空间复杂度
github项目地址:bitcarmanlee easy-algorithm-访谈-实践
欢迎大家,明星,留言一起学习进步。
快,面试题目中出现概率最高的一个,甚至没有。Python实现,直接编码
1.python代码def getMiddle(list,low,high):tmp=list[low]while(low high):while(low high and list[high]tmp):high-=1 list[low]=list[high]while(low high and list[low]tmp):low=1 list[high]=list[low]list[low]=tmp return low def quick sort 1(list,low,high):if low high:middle=get middle(list,low,high) quickSort1(list,low,middle-1) quickSort1(快速布局的相关优化思路如下:1。合理选择支点,选择分区的第一个或最后一个元素作为支点肯定是不合适的。对于订单已经安排好,或者接近订单的情况,将进入最坏情况,时间复杂度下降到O (n {2})。
理想情况下,pivot的选择应该使分区中小于pivot的元素数量与大于pivot的元素数量相似。常见的方法是三中,即取第一项、最后一项、中间一项的中值为支点。当然,这并不能完全避免最坏的情况。因此,通常采用更仔细和严格的枢轴选择方案(对于大型阵列尤其重要)。比如先把大数组平均分成左、中、右三部分。每个部分由三个数字选出,得到一个中位数,然后从得到的三个中位数中找出中位数。
我在javascript v8引擎里看到了另一种选择pivot的方法:认为超过1000个条目的数组是一个大数组,每隔200个左右选择一个元素(不固定),求这些元素中的中值,将第一个和第二个元素相加,求这三个元素中的中值作为pivot。
对了,在现实世界中,你提前对一个数组进行一定顺序的排序太常见了。这种优化必须可用。
2.处理重复元素。如果数组中的所有元素大小相同(或者有很多相同的元素),会发生什么?这是一种边界情况,但它会使快速排序变成最坏的情况,因为无论如何选择pivot,分区结果都会是一边大,另一边小。那这个问题怎么解决呢?或者修改分区过程。思路和上面说的双向分区差不多,但是会更复杂。我们需要三个分区,比pivot小,等于pivot,比pivot大。既然你说了不贴代码,那就到此为止吧。有兴趣的话可以找别人自己实施。
3.优化小阵列的效率已经被很多人提到了。为什么要优化小型阵列?因为规模小,所以快速排序的优势不明显(可能没有优势),递归算法会带来额外的开销。所以对于这种情况,我们可以选择非递归算法来代替。好,那么有两个问题:一个数组有多小才算小数组?什么是替换算法?
通常这个阈值设置为16(v8设置为10),替代算法一般是选择排序。据说设置阈值是为了更好的利用cpu缓存,但是这个问题我不是很清楚。同样,是立即对分区得到的小数组进行选择和排序,还是等到所有分区都完成后,再统一选择和排序,缓存命中率会有一些差异,这个我不了解,也不深入。
3.非递归实现。非递归实现的本质是用栈实现递归操作。具体步骤如下:
申请一个堆栈来存储排序后数组的起始位置和结束位置。
2.将整个数组的起始位置和结束位置放入堆栈。
3.堆栈出数据,对堆栈出的数据进行排序,找到基准数据的最终位置支点。
4.判断起始位置是否小于参考位置pivot-1,如果是,将起始位置和pivot-1作为结束位置进行叠加。
5.判断基准位置枢轴一是否小于终点位置结束,如果小于则将枢轴一作为起始位置,结束作为终点位置进栈
6.判断栈是否为空,如果不为空则重复第三步,否则退出操作。按惯例,空谈不值钱,给我看看代码
包雷磊。有点。edu。堆栈测试;导入Java。util。堆栈;public class Quick { public static int partition(int[]a,int start,int end){ int pivot=a[start];而(开始结束){while(开始结束a[结束]=pivot){ end-;} a[开始]=a[结束];while(start end a[start]=pivot){ start;} a[结束]=a[开始];} a[start]=pivot;返回开始;} public static void recursivequiksort(int[]a,int start,int end){ if(start end){ int position=partition(a,start,end);recursivecqicksort(a,start,position-1);recursivecqicksort(a,位置1,结束);} }公共静态void非递归QuickSort(int[] a) {//存放开始与结束索引stack integer s=new stack integer();//压栈s . push(0);s . push(a .长度-1);//利用循环里实现而(!s . empty()){ int right=s . pop();int left=s . pop();如果(右左){ continue}int i=partition(a,left,right);如果(左i-1) {s.push(左);s . push(I-1);} if(I 1 right){ s . push(I 1);推送服务(右);} } }公共静态void print array(int[]a){ for(int I=0;内务部。长度;I){系统。出去。print(a[I] );}系统。出去。println();}公共静态void main(String[]args){ int[]a={ 1,3,5,7,9,2,4,6,8 };非递归快速排序(一);打印数组(a);}} 代码运行结果
1 2 3 4 5 6 7 8 9