最小的K个数,最大的K个数等需要进行排序的,都可以用到分治的思想,利用快排快速解决
1.快速排序思想
快速排序由C. A. R. Hoare在1960年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
举一个例子:
对 3, 5, 1, 4, 2, 6进行快速排序
在第一次排序的时候,把待比较的值存储在临时空间中,初始值i为最左边的值,j为最右边的值
因为临时变量储存的是最左边的值,所以需要先从右向左进行遍历,否则右边的值会被覆盖。
从右向左找到第一个比temp小的值,位置为j,如第二行j=4时,arr[j]=2,替换a[i]的值。如第二行2,5,1,4,2,6
从左向右找到第一个比temp大的值,位置为i,如第三行i=1时,arr[i]=5,替换a[j]的值。因为在上一次操作中已经替换到a[i].结果如第三行。
继续如上操作,直到最后一次i=j时,temp替换掉arr[i]的,形成
2,1,3,4,5,6的临时有序数组。
对所有的子序列进行如上操作,即可达到全局有序。
最好时间复杂度O(nlogn),当所有的基准值为最小值时,最坏时间复杂度为O(N*N)。对于基准值的选择,最优选择则是把数组恰好二分,不过这只是理想状态,可以对首中尾取平均值进行基准的选择。
空间复杂度为存储栈的空间O(logn)
快速排序代码实现
1 | public void quickSort(int[] arr,int left,int right){ |
快速排序其实就是一个分治的思想:
对所有的子序列进行递归处理,所有的子序列排序,则全局有序
最小的K个数解答
如果运用了快速排序解决了数组有序性问题,则最小的K个数则是前k个数的数组集合
1 | public int[] getLeastNumbers(int[] arr, int k) { |
核心则还是快速排序。
当然对于这个最小K个数,只需要排序到K这个位置即可,对于K之后的位置无需排序。所以可以利用快排思想,找到K位置的基准值,返回之前的数组即可。