题解 | #最小的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;

    }
};
全部评论

相关推荐

2025-12-31 19:23
已编辑
门头沟学院 Java
ssob是已读不回的,字节是压根不敢投的,简历是反反复复改了N遍的,八股是永远背不完的😅😅😅扯远了,道心破碎了,把简历发出来让大伙先看看笑话。再说正事。寒假日常实习还是很难找,连个面试都难约,我不是个例,这是网上普遍反映。不报希望了,趁着2、3月前赶紧做些什么才是。扔几个碎碎念:1.这破简历还能怎么改?写到什么程度才能过实习岗筛选?广大牛友来锐评一下2.火速辅修go,是否可行目前看来是学习成本最小的。首先,很多go实习岗位已经明确要求掌握gin等技术栈,拿java简历投go的时代已经过去了。其次,很多后端的东西,MySQL、Redis这些都是通用的,不用重新学。所以这个问题就具体为:2.1&nbsp;java&amp;go混血简历怎么写第一个项目,仿大麦的微服务,不太好改。因为有用到Redisson、AOP、SpringAI这些java强相关的东西,包装成go需要替换这些方案。第二个,点评魔改。应该可以包装成go,github上也有人用go重写过。2.2&nbsp;java&amp;go通用的轮子RPC直接pass了,太烂大街了。不知道动态线程池能不能做。反正项目上新有风险,不一定来得及,非必要就不开新的项目。补充:别跟我扯RAG了,这玩意已经成新的烂大街了,详见我上一篇的吐槽。3.认真学微调prompt什么的这个半步踩进算法了已经。八股和场景题完全就是另一套,没两三个月搞不定的。约等于换方向
简历中的项目经历要怎么写
点赞 评论 收藏
分享
2025-12-17 12:08
门头沟学院 产品经理
牛客85811352...:1希音不知道算不算大厂 2完全符合,过得很舒服, 3确实只有杂活 领导找我续签到明年3、4月我要继续吗。主要是边实习边秋招这段时间还是有点累
什么是优秀的实习经历
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务