跳到主要内容
C++ 算法
C++ STL 关联容器 set 与 map 使用详解 C++ STL 标准模板库中关联容器 set 与 map 的核心用法。涵盖容器构造、元素插入删除查找、迭代器操作及底层红黑树特性。对比 set 与 multiset、map 与 multimap 的区别,演示 pair 类型在键值对中的应用。结合 LeetCode 实例讲解数组交集、环形链表检测、随机链表复制及前 K 个高频单词的求解方案。
片刻 发布于 2026/3/22 更新于 2026/5/4 6 浏览C++ STL 关联容器 set 与 map 使用详解
容器概述
序列容器和关联容器
STL 中的容器主要分为序列式容器和关联式容器。
序列容器的核心特征:
线性逻辑结构 :元素按存储位置顺序排列,相邻元素在物理存储上可能连续(如 vector)或离散(如 list),但元素间仅通过线性顺序关联。
元素独立性 :任意交换两个元素的位置,容器仍保持合法结构,仅改变元素的排列顺序。
位置驱动访问 :通过位置索引(如 vector[i])或迭代器顺序访问,不依赖元素值的大小或关系。
关联容器的核心特征:
非线性逻辑结构 :通常基于树(如红黑树)或哈希表实现,元素间通过键值的有序性或哈希映射建立关联。
结构敏感性 :交换元素会破坏容器的内部逻辑结构(如树的有序性或哈希表的映射关系),导致后续操作(如查找、插入)失效。
关键字驱动访问 :元素按关键字(Key)存储和检索,而非位置。例如 map 容器通过键值对 (key, value) 存储数据,查找时直接通过 key 定位。
维度 序列式容器 关联式容器 逻辑结构 线性序列(数组、链表等) 非线性结构(树、哈希表等) 元素关联 仅通过位置的顺序关联 通过键值的有序或哈希的映射关联 访问依据 存储位置(索引或迭代器) 关键字(Key) 典型实现 vector、list、deque set、map、unordered_set、unordered_map
set 容器
1. set 容器介绍
set 是关联容器,包含唯一键且已排序的元素。
template <class T ,
class Compare = less<T>,
class Alloc = allocator<T>>
class set;
模板参数说明:
元素类型(T) :set 底层存储的关键字类型,需保证该类型支持比较操作(默认需支持 < 运算符)。
比较器(Compare,默认 less) :用于定义元素间的排序规则。
内存分配器(Allocator,默认 allocator) :负责管理 set 的内存分配与释放。
如需优化内存使用,可自定义分配器。若 T 不支持默认比较或需自定义排序逻辑,可通过仿函数重载比较规则。
2. set 容器的常见构造
#include <iostream>
#
{ lhs < rhs; }
{
{
lhs < rhs;
}
};
{
std::set< > s1;
myints[] = { , , , , };
;
;
;
std::set< , classcomp> s5;
(*fn_pt)( , ) = fncomp;
;
;
}
include
<set>
bool fncomp (int lhs, int rhs)
return
struct
classcomp
bool operator () (const int & lhs, const int & rhs) const
return
int main ()
int
int
10
20
30
40
50
std::set<int > s2 (myints, myints + 5 )
std::set<int > s3 (s2)
std::set<int > s4 (s2. begin(), s2. end())
int
bool
int
int
std::set<int , bool (*) (int ,int ) > s6 (fn_pt)
return
0
3. 容量的操作
std::set::size #include <iostream>
#include <set>
int main () {
std::set<int > myints;
std::cout << "初始状态下的 set 大小的 size 为:" << myints.size () << '\n' ;
for (int i = 0 ; i < 10 ; ++i) myints.insert (i);
std::cout << "插入 10 个元素后 set 大小的 size 为:" << myints.size () << '\n' ;
myints.insert (100 );
std::cout << "插入元素 100 后 set 大小的 size 为:" << myints.size () << '\n' ;
myints.erase (5 );
std::cout << "删除 5 个元素后 set 大小的 size 为:" << myints.size () << '\n' ;
return 0 ;
}
std::set::empty #include <iostream>
#include <set>
int main () {
std::set<int > myset;
myset.insert (20 ); myset.insert (30 ); myset.insert (10 );
std::cout << "myset 容器中的内容为:" ;
while (!myset.empty ()){
std::cout << ' ' << *myset.begin ();
myset.erase (myset.begin ());
}
std::cout << '\n' ;
return 0 ;
}
4. 修改的操作
std::set::clear #include <iostream>
#include <set>
int main () {
std::set<int > myset;
myset.insert (100 ); myset.insert (200 ); myset.insert (300 );
std::cout << "初始状态下 myset 容器中的内容为:" ;
for (std::set<int >::iterator it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
myset.clear ();
myset.insert (1101 ); myset.insert (2202 );
std::cout << "进行清空和插入操作后 myset 容器中的内容为:" ;
for (std::set<int >::iterator it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
return 0 ;
}
std::set::swap #include <iostream>
#include <set>
int main () {
int myints[] = {12 , 75 , 10 , 32 , 20 , 25 };
std::set<int > first (myints, myints + 3 ) ;
std::set<int > second (myints + 3 , myints + 6 ) ;
first.swap (second);
std::cout << "交换后 first 容器中的内容为:" ;
for (std::set<int >::iterator it = first.begin (); it != first.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
std::cout << "交换后 second 容器中的内容为:" ;
for (std::set<int >::iterator it = second.begin (); it != second.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
return 0 ;
}
std::set::insert #include <iostream>
#include <set>
int main () {
std::set<int > myset;
std::set<int >::iterator it;
std::pair<std::set<int >::iterator, bool > ret;
for (int i = 1 ; i <= 5 ; ++i){ myset.insert (i * 10 ); }
ret = myset.insert (20 );
if (ret.second == false ) it = ret.first;
std::cout << "myset 容器中的内容为:" ;
for (it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
myset.insert (it, 25 );
myset.insert (it, 24 );
myset.insert (it, 26 );
std::cout << "myset 容器中的内容为:" ;
for (it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
int myints[] = {5 , 10 , 15 };
myset.insert (myints, myints + 3 );
std::cout << "myset 容器中的内容为:" ;
for (it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
return 0 ;
}
std::set::erase #include <iostream>
#include <set>
int main () {
std::set<int > myset;
std::set<int >::iterator it;
for (int i = 1 ; i < 10 ; i++){ myset.insert (i * 10 ); }
it = myset.begin (); ++it;
myset.erase (it);
myset.erase (40 );
it = myset.find (60 );
myset.erase (it, myset.end ());
std::cout << "myset 容器中的内容为:" ;
for (it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
return 0 ;
}
5. 比较的操作
std::set::key_comp #include <iostream>
#include <set>
int main () {
std::set<int > myset;
std::set<int >::key_compare mycomp = myset.key_comp ();
for (int i = 0 ; i <= 5 ; i++){ myset.insert (i); }
int highest = *myset.rbegin ();
std::set<int >::iterator it = myset.begin ();
do {
std::cout << ' ' << *it;
}while (mycomp (*(++it), highest));
std::cout << '\n' ;
return 0 ;
}
std::set::value_comp #include <iostream>
#include <set>
int main () {
std::set<int > myset;
std::set<int >::value_compare mycomp = myset.value_comp ();
for (int i = 0 ; i <= 5 ; i++){ myset.insert (i); }
int highest = *myset.rbegin ();
std::set<int >::iterator it = myset.begin ();
do {
std::cout << ' ' << *it;
}while (mycomp (*(++it), highest));
std::cout << '\n' ;
return 0 ;
}
6. 其他的操作
std::set::find #include <iostream>
#include <set>
int main () {
std::set<int > myset;
std::set<int >::iterator it;
for (int i = 1 ; i <= 5 ; i++){ myset.insert (i * 10 ); }
it = myset.find (20 ); myset.erase (it);
myset.erase (myset.find (40 ));
std::cout << "myset 容器中的内容为:" ;
for (it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
return 0 ;
}
std::set::count #include <iostream>
#include <set>
int main () {
std::set<int > myset;
for (int i = 1 ; i < 5 ; ++i){ myset.insert (i * 3 ); }
for (int i = 0 ; i < 10 ; ++i){
std::cout << i;
if (myset.count (i) != 0 ) std::cout << "在 myset 容器中\n" ;
else std::cout << "不在 myset 容器中\n" ;
}
return 0 ;
}
std::set::lower_bound / upper_bound / equal_range #include <iostream>
#include <set>
int main () {
std::set<int > myset;
std::set<int >::iterator itlow, itup;
for (int i = 1 ; i < 10 ; i++) myset.insert (i * 10 );
itlow = myset.lower_bound (30 );
itup = myset.upper_bound (60 );
myset.erase (itlow, itup);
std::cout << "myset 容器的内容为:" ;
for (std::set<int >::iterator it = myset.begin (); it != myset.end (); ++it){
std::cout << ' ' << *it;
}
std::cout << '\n' ;
return 0 ;
}
#include <iostream>
#include <set>
int main () {
std::set<int > myset;
for (int i = 1 ; i <= 5 ; i++) myset.insert (i * 10 );
std::pair<std::set<int >::const_iterator, std::set<int >::const_iterator> ret;
ret = myset.equal_range (30 );
std::cout << "lower_bound(ret.first)指向:" << *ret.first << '\n' ;
std::cout << "upper_bound(ret.second)指向:" << *ret.second << '\n' ;
return 0 ;
}
set 容器使用示例
基础特性与遍历 #include <iostream>
#include <set>
using namespace std;
int main () {
set<int > s;
s.insert (5 ); s.insert (2 ); s.insert (7 ); s.insert (5 );
auto it = s.begin ();
while (it != s.end ()){ cout << *it << " " ; ++it; }
cout << endl;
s.insert ({2 , 8 , 3 , 9 });
for (auto e : s){ cout << e << " " ; }
cout << endl;
set<string> strset = {"sort" , "insert" , "add" };
for (auto & e : strset){ cout << e << " " ; }
cout << endl;
return 0 ;
}
迭代器删除与查找 #include <iostream>
#include <set>
using namespace std;
int main () {
set<int > s = {4 , 2 , 7 , 2 , 8 , 5 , 9 };
for (auto & e : s){ cout << e << " " ; } cout << endl;
s.erase (s.begin ());
for (auto e : s){ cout << e << " " ; } cout << endl;
int x; cin >> x;
int num = s.erase (x);
if (num == 0 ){ cout << x << " 不存在!" << endl; }
else { cout << x << " 存在!" << endl; }
cin >> x;
auto pos = s.find (x);
if (pos != s.end ()){ s.erase (pos); }
cin >> x;
if (s.count (x)) cout << x << " 在!" << endl;
else cout << x << " 不存在!" << endl;
return 0 ;
}
lower_bound/upper_bound 应用 #include <iostream>
#include <set>
using namespace std;
int main () {
std::set<int > myset;
for (int i = 1 ; i < 10 ; i++){ myset.insert (i * 10 ); }
auto itlow = myset.lower_bound (30 );
auto itup = myset.upper_bound (60 );
myset.erase (itlow, itup);
for (auto e : myset){ cout << e << " " ; }
cout << endl;
return 0 ;
}
multiset 容器
1. multiset 介绍 multiset 允许元素重复,底层同样基于红黑树实现。
template <class T ,
class Compare = less<T>,
class Alloc = allocator<T>>
class multiset;
2. set 与 multiset 的区别
set :自动去重,容器中元素唯一。
multiset :允许元素重复,侧重按序存储重复数据。
代码示例 #include <iostream>
#include <set>
using namespace std;
int main () {
multiset<int > s = {4 , 2 , 7 , 2 , 4 , 8 , 4 , 5 , 4 , 9 };
auto it = s.begin ();
while (it != s.end ()){ cout << *it << " " ; ++it; }
cout << endl;
int x; cin >> x;
auto pos = s.find (x);
while (pos != s.end () && *pos == x){ cout << *pos << " " ; ++pos; }
cout << endl;
cout << "数量:" << s.count (x) << endl;
cin >> x;
s.erase (x);
for (auto it : s){ cout << it << " " ; }
cout << endl;
return 0 ;
}
pair 容器
1. pair 介绍 pair 用于将两个不同类型的数据组合成一个逻辑单元,位于 <utility> 头文件。
std::pair<Type1, Type2> pairName (value1, value2) ;
2. 特性
元素访问 :通过 first 和 second 成员变量访问。
比较操作 :支持按字典序比较(先比 first,若相等再比 second)。
3. 使用示例
typedef pair<const Key, T> value_type;
template <class T1 , class T2 >
struct pair {
typedef T1 first_type;
typedef T2 second_type;
T1 _first;
T2 _second;
pair ():_first(T1 ()),_second(T2 ()){}
pair (const T1& a, const T2& b):_first(a),_second(b){}
template <class U, class V>
pair (const pair<U, V>& pr) :_first(pr.first),_second(pr.second){ }
};
template <class T1, class T2>
inline pair<T1, T2> make_pair (T1 x, T2 y) {
return (pair <T1, T2>(x, y));
}
map 容器
1. map 容器介绍 template <class Key ,
class T ,
class Compare = less<Key>,
class Alloc = allocator<pair<const Key, T>>
class map;
键类型(Key) :map 中用于索引和排序的关键字类型。
映射值类型(T) :与键关联的具体数据类型。
比较器(Compare) :用于定义键之间的排序规则。
内存分配器(Alloc) :负责管理 map 底层存储的键值对的内存分配。
2. map 容器的常见构造 #include <iostream>
#include <map>
int main () {
std::map<char , int > m1;
m1['a' ] = 10 ; m1['b' ] = 30 ;
std::map<char , int > m2 (m1. begin(), m1. end()) ;
std::map<char , int > m3 (m2) ;
struct classcomp { bool operator () (const char & lhs, const char & rhs) const { return lhs < rhs; }};
std::map<char , int , classcomp> m4;
return 0 ;
}
3. 容量的操作
std::map::size / empty #include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 101 ; mymap['b' ] = 202 ; mymap['c' ] = 302 ;
std::cout << "mymap 的大小为:" << mymap.size () << '\n' ;
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 10 ; mymap['b' ] = 20 ; mymap['c' ] = 30 ;
while (!mymap.empty ()){
std::cout << mymap.begin ()->first << " => " << mymap.begin ()->second << '\n' ;
mymap.erase (mymap.begin ());
}
return 0 ;
}
4. 访问的操作
std::map::operator[] #include <iostream>
#include <map>
#include <string>
int main () {
std::map<char , std::string> mymap;
mymap['a' ] = "an element" ;
mymap['b' ] = "another element" ;
mymap['c' ] = mymap['b' ];
std::cout << "mymap['a'] is " << mymap['a' ] << '\n' ;
std::cout << "mymap['d'] is " << mymap['d' ] << '\n' ;
std::cout << "mymap now contains " << mymap.size () << " elements.\n" ;
return 0 ;
}
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main () {
map<string, string> dict;
dict.insert (make_pair ("sort" , "排序" ));
dict["insert" ];
dict["left" ] = "左边" ;
dict["left" ] = "左边、剩余" ;
cout << dict["left" ] << endl;
return 0 ;
}
5. 修改的操作
std::map::clear / swap / insert / erase #include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['x' ] = 100 ; mymap['y' ] = 200 ; mymap['z' ] = 300 ;
mymap.clear ();
mymap['a' ] = 1101 ; mymap['b' ] = 2202 ;
for (std::map<char , int >::iterator it = mymap.begin (); it != mymap.end (); ++it){
std::cout << it->first << " => " << it->second << '\n' ;
}
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > foo, bar;
foo['x' ] = 100 ; foo['y' ] = 200 ;
bar['a' ] = 11 ; bar['b' ] = 22 ; bar['c' ] = 33 ;
foo.swap (bar);
for (std::map<char , int >::iterator it = foo.begin (); it != foo.end (); ++it){
std::cout << it->first << " => " << it->second << '\n' ;
}
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap.insert (std::pair <char , int >('a' , 100 ));
mymap.insert (std::pair <char , int >('z' , 200 ));
std::pair<std::map<char , int >::iterator, bool > ret;
ret = mymap.insert (std::pair <char , int >('z' , 500 ));
if (ret.second == false ){
std::cout << "元素'z'已经存在\n" ;
std::cout << "其值为:" << ret.first->second << '\n' ;
}
std::map<char , int >::iterator it = mymap.begin ();
mymap.insert (it, std::pair <char , int >('b' , 300 ));
std::map<char , int > anothermap;
anothermap.insert (mymap.begin (), mymap.find ('c' ));
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 10 ; mymap['b' ] = 20 ; mymap['c' ] = 30 ;
mymap['d' ] = 40 ; mymap['e' ] = 50 ; mymap['f' ] = 60 ;
it = mymap.find ('b' ); mymap.erase (it);
mymap.erase ('c' );
it = mymap.find ('e' ); mymap.erase (it, mymap.end ());
for (it = mymap.begin (); it != mymap.end (); ++it){
std::cout << it->first << " => " << it->second << '\n' ;
}
return 0 ;
}
6. 其他的操作
std::map::find / count / lower_bound / upper_bound / equal_range #include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 50 ; mymap['b' ] = 100 ; mymap['c' ] = 150 ; mymap['d' ] = 200 ;
it = mymap.find ('b' );
if (it != mymap.end ()) mymap.erase (it);
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 101 ; mymap['c' ] = 202 ; mymap['f' ] = 303 ;
for (char c = 'a' ; c < 'h' ; c++){
std::cout << c;
if (mymap.count (c) > 0 )
std::cout << "是 mymap 容器中的元素\n" ;
else
std::cout << "不是 mymap 容器中的元素\n" ;
}
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 20 ; mymap['b' ] = 40 ; mymap['c' ] = 60 ; mymap['d' ] = 80 ; mymap['e' ] = 100 ;
itlow = mymap.lower_bound ('b' );
itup = mymap.upper_bound ('d' );
mymap.erase (itlow, itup);
return 0 ;
}
#include <iostream>
#include <map>
int main () {
std::map<char , int > mymap;
mymap['a' ] = 10 ; mymap['b' ] = 20 ; mymap['c' ] = 30 ;
std::pair<std::map<char , int >::iterator, std::map<char , int >::iterator> ret;
ret = mymap.equal_range ('b' );
std::cout << "lower_bound 指向的元素是:" << ret.first->first << " => " << ret.first->second << '\n' ;
std::cout << "upper_bound 指向的元素是:" << ret.second->first << " => " << ret.second->second << '\n' ;
return 0 ;
}
7. map 核心接口设计说明 #include <map>
using namespace std;
using key_type = ;
using mapped_type = ;
using value_type = pair<const key_type, mapped_type>;
iterator find (const key_type& k) ;
pair<iterator, bool > insert (const value_type& val) ;
mapped_type& operator [](const key_type& k){
pair<iterator, bool > ret = insert ({k, mapped_type ()});
iterator it = ret.first;
return it->second;
}
8. map 使用示例 #include <iostream>
#include <map>
using namespace std;
int main () {
map<string, string> dict = {{"left" , "左边" }, {"right" , "右边" }};
auto it = dict.begin ();
while (it != dict.end ()){ cout << it->first << ":" << it->second << endl; ++it; }
dict.insert (make_pair ("sort" , "排序" ));
dict.insert ({"auto" , "自动的" });
for (const auto & e : dict){ cout << e.first << ":" << e.second << endl; }
return 0 ;
}
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main () {
string arr[] = {"苹果" , "西瓜" , "苹果" , "西瓜" , "苹果" };
map<string, int > countMap;
for (const auto & str : arr){
auto ret = countMap.find (str);
if (ret == countMap.end ()) countMap.insert ({str, 1 });
else ret->second++;
}
for (const auto & e : countMap){ cout << e.first << ":" << e.second << endl; }
return 0 ;
}
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main () {
string arr[] = {"苹果" , "西瓜" , "苹果" , "西瓜" , "苹果" };
map<string, int > countMap;
for (const auto & str : arr){ countMap[str]++; }
for (const auto & e : countMap){ cout << e.first << ":" << e.second << endl; }
return 0 ;
}
multimap 容器
1. multimap 介绍 multimap 允许键冗余,适合存'一对多'的映射关系。
template <class Key ,
class T ,
class Compare = less<Key>,
class Alloc = allocator<pair<const Key, T>>
class multimap;
2. map 与 multimap 的区别
map :自动保证键唯一,容器中每个键对应唯一的映射关系。
multimap :允许键冗余,侧重按序存储键可重复的映射数据。
注意:multimap 不支持 operator[],因为键可冗余的场景下无法明确指定修改哪一个键对应的值。
OJ 练习
1. set 相关题目 class Solution {
public :
vector<int > intersection (vector<int >& nums1, vector<int >& nums2) {
set<int > s1 (nums1. begin(), nums1. end()) ;
set<int > s2 (nums2. begin(), nums2. end()) ;
vector<int > ret;
auto it1 = s1. begin ();
auto it2 = s2. begin ();
while (it1 != s1. end () && it2 != s2. end ()){
if (*it1 < *it2){ it1++; }
else if (*it1 > *it2){ it2++; }
else {
ret.push_back (*it1);
it1++; it2++;
}
}
return ret;
}
};
class Solution {
public :
ListNode *detectCycle (ListNode *head) {
set<ListNode*> s;
ListNode* cur = head;
while (cur){
auto ret = s.insert (cur);
if (ret.second == false ) return cur;
cur = cur->next;
}
return nullptr ;
}
};
2. map 相关题目 class Solution {
public :
Node* copyRandomList (Node* head) {
map<Node*, Node*> m;
Node* copyHead = nullptr ;
Node* copyTail = nullptr ;
Node* curr = head;
while (curr){
if (copyTail == nullptr ){
copyHead = copyTail = new Node (curr->val);
} else {
copyTail->next = new Node (curr->val);
copyTail = copyTail->next;
}
m[curr] = copyTail;
curr = curr->next;
}
curr = head;
Node* copy = copyHead;
while (curr){
if (curr->random == nullptr ){
copy->random = nullptr ;
} else {
copy->random = m[curr->random];
}
curr = curr->next;
copy = copy->next;
}
return copyHead;
}
};
方法一:基于 stable_sort 排序 class Solution {
public :
struct Compare {
bool operator () (const pair<string, int >& x, const pair<string, int >& y) const {
return x.second > y.second;
}
};
vector<string> topKFrequent (vector<string>& words, int k) {
map<string, int > m;
for (auto & e : words){ m[e]++; }
vector<pair<string, int >> v (m.begin (), m.end ());
stable_sort (v.begin (), v.end (), Compare ());
vector<string> ret;
for (int i = 0 ; i < k; i++){ ret.push_back (v[i].first); }
return ret;
}
};
方法二:基于 sort 排序 class Solution {
public :
struct Compare {
bool operator () (const pair<string, int >& x, const pair<string, int >& y) const {
return x.second > y.second || (x.second == y.second && x.first < y.first);
}
};
vector<string> topKFrequent (vector<string>& words, int k) {
map<string, int > m;
for (auto & e : words){ m[e]++; }
vector<pair<string, int >> v (m.begin (), m.end ());
sort (v.begin (), v.end (), Compare ());
vector<string> ret;
for (int i = 0 ; i < k; i++){ ret.push_back (v[i].first); }
return ret;
}
};
方法三:基于 priority_queue 大顶堆 class Solution {
public :
struct Compare {
bool operator () (const pair<string, int >& x, const pair<string, int >& y) const {
return x.second < y.second || (x.second == y.second && x.first > y.first);
}
};
vector<string> topKFrequent (vector<string>& words, int k) {
map<string, int > m;
for (auto & e : words){ m[e]++; }
priority_queue<pair<string, int >, vector<pair<string, int >>, Compare> p (m.begin (), m.end ());
vector<string> ret;
for (int i = 0 ; i < k; i++){
ret.push_back (p.top ().first);
p.pop ();
}
return ret;
}
};
相关免费在线工具 加密/解密文本 使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
Gemini 图片去水印 基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
Markdown转HTML 将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online
HTML转Markdown 将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online