题解 | #最小的K个数#

最小的K个数

http://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf

时间复杂度O(nlogn)很容易联想到快速排序,结合题目暗示的顺序无关可以进一步优化快排变成半边快排

首先,简单说一下快排的中心思想,为后续解释做准备。快排的基础是递归,每次递归都会有一个中间值,保证中间值左边的数小于中间值,右边的数大于中间值;然后进行递归,以中间值为分界线对左边数组进行快排,再对右边数组进行快排。

通常一层快排结束后,需要对两边分别进行迭代快排。 但如果只需找最小的K个数,就可以在快排基础上进一步优化:

1、如果中间值位置index恰好等于K-1,那么不必再进行进一步排序,左边的K个数字即是答案(这K个并不一定有序);

2、如果中间值小于K-1,那么左边这K个数字必定在答案里,只需对中间值右边部分进行迭代快排

3、如果中间值大于K-1,那么右边这N-K个必定不是答案,只需对中间值左边部分进行迭代快排

快排的写法因人而异,该思路最大的亮点是半边快排。

import java.util.ArrayList;

public class Solution {
    public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
        ArrayList<Integer> res = new ArrayList<>();
        halfQuickSort(input, 0, input.length-1, k);
        for(int i=0;i<k;i++){
            res.add(input[i]);
        }
        return res;
    }
    
    private static void halfQuickSort(int[] arr, int l, int r, int k){
        if(l>=r) return;
        int i=l, j=r, base= arr[l], tmp;
        while(i<j){
            while (i<j && arr[j]>=base){
                j--;
            }
            while (i<j && arr[i]<=base){
                i++;
            }
            if(i<j){
                tmp = arr[i];
                arr[i] = arr[j];
                arr[j] = tmp;
            }
        }
        arr[l] = arr[i];
        arr[i] = base;
        if(i==k-1){
            return;
        }else if(i<k-1){
            halfQuickSort(arr, i+1, r, k);
        }else{
            halfQuickSort(arr, l, i-1, k);
        }
    }
}
全部评论

相关推荐

10-30 22:18
已编辑
毛坦厂中学 C++
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务