牛客网《剑指Offer》 编程 29.最小的k个数(使用c++提供的set或者multiset)

本文介绍了一种使用C++ STL中的multiset数据结构,解决在一组整数中找到最小的K个数的问题。通过遍历输入数组,利用multiset的特性,确保容器中始终保存着最小的K个数。

题目描述

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

解题思路

此次使用不改变原数组的方法。使用c++STL中的set或者multiset来实现。这两个模板底层的实现都是红黑树。即平衡的二叉搜索树。以下是对set和multiset的简单介绍:

STL说明
set<T>按照从小到大顺序排列的set,元素不允许重复
set<T,op>按照op排列的set,元素不允许重复
multiset<T>从小到大顺序排列的mulitset,只是元素允许重复
multiset<T,op>按照op排列的set,元素允许重复

op如果是less<T>,就是从小到大;op是greater<T>就是从大到小。

遍历待选数组。

当set或者multiset的大小不大于k的时候,可以直接往里面添加元素;

但是当set或者multiset的大小等于k的时候,此时要将当前元素与容器中的最大的元素进行比较。如果大于,则进行下一轮循环;如果小于则将容器中的最大的元素删除掉,将当前元素插入容器。

代码实现

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
        multiset<int,greater<int> > leastNumber;
        if(k<1||input.size()<k){
            return vector<int>();
        }
        for(vector<int>::iterator iter=input.begin();iter!=input.end();iter++){
            if(leastNumber.size()<k){//如果set没有填满,则直接插入;
                leastNumber.insert(*iter);
            }
            else{//如果set已经满了,则应该删除其中最大的。
                multiset<int,greater<int> >::iterator setBegin=leastNumber.begin();
                if((*iter)<*(leastNumber.begin())){
                    leastNumber.erase(setBegin);
                    leastNumber.insert(*iter);
                }
            }
        }
        vector<int> res(leastNumber.begin(),leastNumber.end());
        return res;
    }
};

 

C++中,`set` 和 `multiset` 都属于关联容器,存储的元素都会根据元素的值自动进行排序。但两者存在以下区别: ### 元素唯一性 - `set` 容器中不允许有重复的元素,当插入重复元素时,插入操作会失败。例如以下代码: ```cpp #include <iostream> #include <set> using namespace std; void test01() { set<int> s; pair<set<int>::iterator, bool> ret = s.insert(10); if (ret.second) { cout << "第一次插入成功" << endl; } else { cout << "第一次插入失败" << endl; } ret = s.insert(10); if (ret.second) { cout << "第二次插入成功" << endl; } else { cout << "第二次插入失败" << endl; } } int main() { test01(); return 0; } ``` 该代码展示了 `set` 插入重复元素时,第二次插入会失败[^1]。 - `multiset` 容器允许有重复的元素,插入重复元素会成功。如下代码: ```cpp #include <iostream> #include <set> using namespace std; void testMultiset() { multiset<int> ms; ms.insert(10); ms.insert(10); ms.insert(10); ms.insert(10); for (multiset<int>::iterator it = ms.begin(); it != ms.end(); it++) { cout << *it << " "; } cout << endl; } int main() { testMultiset(); return 0; } ``` 该代码展示了 `multiset` 可以多次插入相同元素,且能正常存储并遍历输出[^1]。 ### 容器大小 由于 `set` 不允许重复元素,而 `multiset` 允许,所以对于包含重复元素的初始化序列,两者的大小可能不同。例如: ```cpp #include <string> #include <iostream> #include <set> #include <vector> using namespace std; int main() { vector<int> ivec; for(int i = 0; i!= 10;++i) { ivec.push_back(i); ivec.push_back(i); } set<int> iset(ivec.begin(),ivec.end()); multiset<int> miset(ivec.begin(),ivec.end()); cout << iset.size() << endl; cout << miset.size() << endl; cout << ivec.size() << endl; return 0; } ``` 此代码中,`iset` 的大小为 10,`miset` 的大小为 20,因为 `iset` 会去重,而 `miset` 保留所有元素[^2]。 ### 插入返回值 - `set` 的 `insert` 方法返回一个 `pair`,其中 `pair` 的 `second` 成员是一个布尔值,表示插入是否成功。 - `multiset` 的 `insert` 方法返回一个迭代器,指向新插入元素的位置,因为 `multiset` 插入总是成功,所以不需要返回布尔值表示插入结果。 ### 找元素 - 在 `set` 中找元素,若找到,返回指向该元素的迭代器;若未找到,返回 `end()` 迭代器。 - 在 `multiset` 中找元素,若找到,返回指向该元素的迭代器;由于可能存在多个相同元素,`multiset` 还提供了 `count` 方法用于统计某个元素的出现次数。 ### 元素删除 - 在 `set` 中删除元素,若元素存在则删除并返回 1,若不存在则返回 0。 - 在 `multiset` 中删除元素,会删除所有与指定值相等的元素,并返回被删除元素的数量。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值