快速排序的时间复杂度为O(N*logN)。
算法思路 在快速排序中需要有一个Partition函数,这个方法是在数组中选择一个数字,然后把数组中的数字分为两个部分,比选择的数字小的函数移到数组的左边,比选择的数字大的数字移到数组的右边。这个函数的实现如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 function partition (list, start, end ) { var mid = Math .floor((start + end)/2 ); swap(list, mid , end); var small = start - 1 ; for (let i = start; i < end; i++) { if (list[i] < list[end]){ small++; if (small !== i){ swap(list, i, small); } } } small++; swap(list, small, end); return small; } function swap (list,i,j ) { let tmp=list[i]; list[i]=list[j]; list[j]=tmp; }
算法解释 我来解释一下这个函数。
在数组中选取中间的数,然后从前到后遍历,如果某个数比选定的数小,则交换位置。
一个很重要的变量是small,这个变量是用来统计比listend 小的数,当list[i]<list[end],small加一,然后将所有比list[end]小的数,全都交换到前面去。
最后small的位置存放的是选定的数,在这个数前面的数全是小于它,后面的全部大于它。接下需要的就是使用一个递归函数,对选定数之前的数组和选定数之后的数组再进行排序。
1 2 3 4 5 6 7 8 9 10 11 12 function quickSort (list, start, end ) { if (start === end){ return ; } var index = partition(list, start, end); if (index > start){ quickSort(list, start, index - 1 ); } if (index < end){ quickSort(list, index + 1 , end); } }
partition方法应用 在快速排序中的partition方法能用到的地方很多,比如,在剑指offer的面试题29中:数组中出现次数超过一半的数字。也用到了partition。
剑指offer29题 这道题可以先对数组做一次partition,判断返回的数是否正好在n/2位置,则这个数就是我们要找的数;如果返回的数在大于n/2,则中位数在这个数的左边;如果返回的数在小于n/2,则中位数在这个数的右边。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function moreThanHalfNum (list, length ) { var start = 0 ; var end = list.length - 1 ; var mid = Math .floor((start + end)/2 ); var index = partition(list, length, start, end); while (index !== mid){ if (index > mid) { end = index - 1 ; index = partition(list, length, start, end); } else { start = index + 1 ; index = partition(list, length, start, end); } } var result = list[mid]; return result; }
剑指offer30题 再比如在剑指offer的面试题30:最小的k个数,也用到了partition。因为在partition中,将小于选定数的数都放在选定数的前面,大于选定数的数都放在选定数的后面,因此这道题要找出最小的k个数,只需要找到partition的返回值index===k-1即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function getLeastNumbers (list,k ) { var start = 0 ; var end = list.length - 1 ; var result=[]; var index = partition(list, length, start, end); while (index !== k - 1 ) { if (index > k - 1 ){ end = index - 1 ; index = partition(list, length, start, end); } else { start = index + 1 ; index = partition(list, length, start, end); } } for (let i=0 ;i<k;i++){ result.push(list[i]); } console .log(result); }