题解 | #最小的K个数#

最小的K个数

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

思路

参考剑指offer
1、首先使用快排的思想,对一个数组进行分割,大于某个值的在其右侧,小于某个值的在其左侧,该函数(Partition)返回一个索引,代表选择的数字的下标(可能有点绕)。
2、然后就是根据这个返回的索引和k-1(需要k个数,下标范围就是0~k-1)比较,若返回的index<k-1,那么说明第k-1小的数字在index的右侧,更新区间,计算新的index。

代码

class Solution {
public:

    void swap(int& a, int& b){
        int tmp = a;
        a = b;
        b = tmp;
    }

    // 对下标为i的构建堆
    void heapify(vector<int>& arr, int n, int i ){
        if(i>n){return;}
        int c1 = 2*i+1;
        int c2 = 2*i+2;
        int min_index = i;

        if(c1<=n && arr[c1]<arr[min_index]){
            min_index = c1;
        }
        if(c2<=n && arr[c2]<arr[min_index]){
            min_index = c2;
        }

        //min_index = 
        if(min_index==i){
            ;
        }

        else{
            swap(arr[min_index], arr[i]);
        }

        // 递归
        heapify(arr, n, c1);
        heapify(arr, n, c2);

        return;

    }

    // 构建堆
    void build_heap(vector<int>& arr, int n){
        // 找到第一个构建堆的节点
        int parent = (n-1)/2;
        while(parent>=0){
            heapify(arr, n, parent);
            parent--;
        }
    }


    // 快速排序
    int Partition(vector<int>& arr, int L, int R){
        int left = L;
        int right = R;
        int key = arr[left];
        while(left<right){
            while(left<right && arr[right] >= key){
                right--;
            }
            arr[left] = arr[right];
//             left++;

            while(left < right && arr[left]<=key){
                left++;
            }
            arr[right] = arr[left];

        }
        arr[left] = key;
        return left;

    }

    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
//         // 方法1 傻子排序
//         sort(input.begin(), input.end());
//         vector<int> res;
//         res.assign(input.begin(), input.begin()+k);
//         return res;

        /*
        // 方法2 堆排序,通过构建堆
        vector<int> res;
        int count = 0;
        int len = input.size()-1;
        while(count<k){
            build_heap(input, len);        // 最小值放在堆顶
            swap(input[0], input[len]);
            res.push_back(input[len]);
            len--;
            count++;
        }
        return res;
        */

        // 方法3 利用快排
        if(k==0){
//             vector
            return vector<int>();
        }
        int start = 0;
        int end = input.size()-1;
        int index = Partition(input, start, end);

        while(index!=k-1){
            if(index<k-1){
                start = index+1;
                index = Partition(input, start, end);
            }
            else{
                end = index-1;
                index = Partition(input, start, end);
            }


        }

        vector<int> res;
        res.assign(input.begin(), input.begin()+index+1);

        return res;

    }
};
全部评论

相关推荐

11-01 08:48
门头沟学院 C++
伤心的候选人在吵架:佬你不要的,能不能拿户口本证明过户给我。。球球了
点赞 评论 收藏
分享
面试摇了我吧:啊哈哈面试提前五个小时发,点击不能参加就是放弃
点赞 评论 收藏
分享
评论
点赞
收藏
分享
牛客网
牛客企业服务