剑指offer 最小的k个数(C++)

博客围绕输入n个整数找出其中最小的K个数的问题展开,介绍了三种思路。一是对数组排序后输出前k个数,用快速排序,时间复杂度O(nlogn);二是用partition函数,时间复杂度O(n);三是使用小顶堆(优先队列),时间复杂度O(nlog(k)),还介绍了priority_queue的用法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

思路1:先对数组从小达到进行排序,输出前k个数。快速排序,时间复杂度:O(nlogn)。

代码提交页

代码:

class Solution {
 
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        int len = input.size();
        int low=0;
        int high=len-1;
        vector<int> res;
        if(len<=0 || k>len) return res;
        quick_sort(input, low, high);
        for(int i=0; i<k; i++)
            res.push_back(input[i]);
        return res;
    }
    void quick_sort(vector<int>& output, int start, int end)
    {
        int index=start;
        int i=start;
        int j=end;
        int base=output[index];
        while(i<j)
        {
            while(i<j && output[j]>=base) j--;
            output[i]=output[j];
            while(i<j && output[i]<=base) i++;
            output[j]=output[i];
        }
        index = i;
        output[index] = base;
        if(i-start>1) quick_sort(output, start, i-1);
        if(end-j>1) quick_sort(output, j+1, end);
    }
};

思路2:使用partition函数(进行一次快速排序,用哨兵数分割数组中的数据),时间复杂度:O(n)

代码:

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        int high = input.size()-1;
        int low = 0;
        if((high+1)<k || k<=0 || input.empty()) return res;
        int index = partition(input,low,high);
        for(int i=0; i<k; i++)
        {
            while(index!=i)
            {
                if(index<k) low=index+1;
                else high=index-1;
                index = partition(input,low,high);
            }
            res.push_back(input[index]);
        }
        return res;
    }
    int partition(vector<int>& nums, int low, int high)
    {
        if(low<0 || high>nums.size() || low>high) return -1;
        if(low==high) return low;
        int base=nums[low];
        while(low<high)
        {
            while(low<high && nums[high]>=base) high--;
            nums[low]=nums[high];
            while(low<high && nums[low]<=base) low++;
            nums[high]=nums[low];
        }
        nums[low]=base;
        return low;
    }
};

思路3:小顶堆(优先队列),时间复杂度:O(nlog(k)).

STL中的优先队列默认是大顶堆,这里生成小顶堆即可。 

priority_queue的用法

模板申明带3个参数:priority_queue<Type, Container, Functional>,其中Type 为数据类型,Container为保存数据的容器,Functional 为元素比较方式。Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list。STL里面默认用的是vector,大顶堆(降序),队头元素最大。

c.top()

返回队列头部数据

c.push(elem)

在队列尾部增加elem数据

 c.pop()

队列头部数据出队

代码:

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        vector<int> res;
        if(k<=0 || k>input.size()) return res;
        priority_queue<int> q;   // STL中的优先队列默认是大顶堆 
        unsigned int i=0; 
        while(i<input.size())
        {
            q.push(input[i]);
            if(q.size()>k) q.pop();
            i++;
        }
        while(!q.empty())
        {
            res.push_back(q.top()); // C语言中的top()可返回顶部元素的值,也可返回顶部元素的指针,程序员自行设计; C++的STL中top()返回的是顶部的值
            q.pop();
        }
        return res;
    }
};

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值