面试时最常问的就是排序算法,所以总结一下这个过程中我遇到的问题:
叙述**排序算法思想,然后写代码;最常问的是快排;
各个排序的时间复杂度,一般情况下都说的是平均。首先还是会问快排,nlogn,然后问同样复杂度的排序算法,合并排序、堆排序、shell排序。(刚开始的时候一直特别害怕复杂度,因为感觉自己不清楚,面试过程中突然感觉,只要进行了折半,复杂度就是nlogn。所以知道各个排序的思想,还是很好想出来的,不需要死记硬背)
后来就问合并排序和快排它们处理数据的特征。因为根本没有遇到这样的问题,没有思路,面试完之后百度给出的答案也不满意。接着在其他公司面试中,
- 面试官问快排最坏情况下复杂度是多少? 答n的平方。
- 又问:最坏是什么情况下。想了一下快排,就是一次排序将基准元素放到相应的位置。然后再左右排。
- 答:基准元素每次都放到最末尾的时候。面试官听后,说,其实就是有序的情况下。是啊,我怎么没有想到。然后也完美的解决了上述合并排序和快排处理数据特征的问题。如果数据是有序的,用合并,是杂乱的用快排。想想自己好笨呀。
如果涉及顺序不能改变的,即“一个数组中有字母、数字,处理使数字都在字母的后面,且字母和数字各自按大小排列,且字母和数字的相对顺序和原数组保持不变,且in-place”。关键点,
- 数字在字母后面,说明数字权重大、字母权重小,且各自排序,则排序。而选用哪种排序呢?
- 相对位置保持不变 – 则是排序算法必须稳定
- in-place,则O(1)空间;
- 根据上述要求,由下表知,则冒泡排序、插入排序、归并排序符合条件。
故下面总结一个各个排序思想和最好最坏复杂度的情况:
直接插入排序:将待排序的数插入已排好序的数组中。最好:待排序数组已有序;
折半插入排序:将待排序的数折半查找插入排好序的数组中。
冒泡排序:每次迭代将最大元(or最小元)放大上面,改进冒泡(标记最后变动位置),这样最好情况为数组有序。
简单选择排序:每次选出最小or最大的元素放到最右边or最左边。
快速排序:默认第一个元素为基准元素,将基准元素放到相应的位置(即整个数组排好序时,其应该在的位置。),左侧的均比其小,右侧的均比其大。最坏:数组有序。所以为了避免此类现象,一般选取随机取基准元素。
堆排序:最小堆,即左右儿子均比父亲大,最大堆反之。
合并排序:将数组折半,然后分别排好,再将排好序的子数组合并。最好:已排好序。