【C++】第十八節—一文萬字詳解 | map和set的使用

嗨,我是云邊有個稻草人,與你分享C++領域專業知識(*^▽^*)

《C++》本篇文章所屬專欄—持續更新中—歡迎訂閱—

?

目錄

一、序列式容器和關聯式容器

二、set系列的使用

2.1?set和multiset參考?檔

2.2 set類的介紹

2.3 set的構造和迭代器

2.4 set的增刪查

2.5 insert和迭代器遍歷使用樣例

2.6 find和erase使用樣例

【erase+find+count】?

【lower_bound+upper_bound】?

2.7 multiset和set的差異

2.8?349. 兩個數組的交集 - 力扣(LeetCode)

2.9?142. 環形鏈表 II - 力扣(LeetCode)

三、map系列的使用

3.1 map和multimap參考文檔

3.2 map類的介紹

3.3 pair類型介紹

3.4 map的構造

3.5 map的增刪查

3.6?構造遍歷及增刪查使?樣例

3.7?map的數據修改+map的迭代器和[ ]功能樣例

【應用1】?

【應用2】

3.8?multimap和map的差異

3.9?138. 隨機鏈表的復制 - 力扣(LeetCode)

3.10?692. 前K個高頻單詞 - 力扣(LeetCode)


正文開始——

一、序列式容器和關聯式容器

前?我們已經接觸過STL中的部分容器如:string、vector、list、deque、array、forward_list等,這些容器統稱為序列式容器,因為邏輯結構為線性序列的數據結構,兩個位置存儲的值之間?般沒有緊密的關聯關系,比如交換?下,其依舊是序列式容器。順序容器中的元素是按他們在容器中的存儲位置來順序保存和訪問的。

關聯式容器也是用來存儲數據的,與序列式容器不同的是,關聯式容器邏輯結構通常是?線性結構, 兩個位置有緊密的關聯關系,交換?下,其存儲結構就被破壞了。序列容器中的元素是按關鍵字來保存和訪問的。關聯式容器有map/set系列和unordered_map/unordered_set系列。 本章節講解的map和set底層是紅?樹,紅?樹是?棵平衡?叉搜索樹

set是key搜索場景的結構, map是key/value搜索場景的結構。


二、set系列的使用

2.1?set和multiset參考?檔

<set> - C++ Reference

2.2 set類的介紹

set的聲明如下,T就是set底層關鍵字的類型,也就是我們上面說的key

  • set默認要求T支持小于比較,如果不支持或者想按自己的需求走可以自行實現仿函數傳給第二個模版參數
  • set底層存儲數據的內存是從空間配置器申請的,如果需要可以自己實現內存池,傳給第三個參數。
  • ?般情況下,我們都不需要傳后兩個模版參數。
  • set底層是用紅黑樹實現,增刪查效率是 ,迭代器遍歷是走的搜索樹的中序,所以是有序的。 O(logN)
  • 前?部分我們已經學習了vector/list等容器的使用,STL容器接口設計,高度相似,所以這?我們就不再?個接??個接?的介紹,?是直接帶著?家看?檔,挑?較重要的接?進行介紹。
2.3 set的構造和迭代器

set的構造我們關注以下幾個接口即可。

set?持正向和反向迭代遍歷,遍歷默認按升序順序,因為底層是?叉搜索樹,迭代器遍歷走的中序;支持迭代器就意味著?持范圍for,set的iterator和const_iterator都不?持迭代器修改數據,修改關鍵字數據破壞了底層搜索樹的結構。

// empty (1) ?參默認構造
explicit set (const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());// range (2) 迭代器區間構造
template <class InputIterator>
set (InputIterator first, InputIterator last,
const key_compare& comp = key_compare(),
const allocator_type& = allocator_type());// copy (3) 拷?構造
set (const set& x);// initializer list (5) initializer 列表構造
set (initializer_list<value_type> il,
const key_compare& comp = key_compare(),
const allocator_type& alloc = allocator_type());// 迭代器是?個雙向迭代器
iterator -> a bidirectional iterator to const value_type// 正向迭代器
iterator begin();
iterator end();// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();
2.4 set的增刪查

set的增刪查關注以下?個接?即可:

Member types
key_type -> The first template parameter (T)
value_type -> The first template parameter (T)// 單個數據插?,如果已經存在則插?失敗
pair<iterator,bool> insert (const value_type& val);// 列表插?,已經在容器中存在的值不會插?
void insert (initializer_list<value_type> il);// 迭代器區間插?,已經在容器中存在的值不會插?
template <class InputIterator>
void insert (InputIterator first, InputIterator last);// 查找val,返回val所在的迭代器,沒有找到返回end()
iterator find (const value_type& val);// 查找val,返回Val的個數
size_type count (const value_type& val) const;// 刪除?個迭代器位置的值
iterator erase (const_iterator position);// 刪除val,val不存在返回0,存在返回1
size_type erase (const value_type& val);// 刪除?段迭代器區間的值
iterator erase (const_iterator first, const_iterator last);// 返回?于等val位置的迭代器
iterator lower_bound (const value_type& val) const;// 返回?于val位置的迭代器
iterator upper_bound (const value_type& val) const;
2.5 insert和迭代器遍歷使用樣例
#include<set>
#include<iostream>using namespace std;int main()
{//去重+升序排序set<int> s1;//去重+排降序(傳一個大于的仿函數)set<int, greater<int>> s2;s2.insert(1);s2.insert(4);s2.insert(-2);s2.insert(100);//使用迭代器set<int>::iterator it = s2.begin();//auto it = s2.begin();while (it != s2.end()){cout << *it << " ";it++;}cout << endl;//使用范圍for打印for (auto e : s2){cout << e << " ";}cout << endl;//支持插入一段initializer_list列表值,已經存在的值插入失敗s2.insert({ 2, 3, 4, 5 });for (auto e : s2){cout << e << " ";}cout << endl;//set里面存如string類型的值set<string> strset = { "sort","animal","list","young" };//遍歷strset比較ASCII碼大小進行插入,注意這里并不是比較字符串的長度//注意下面e最好使用引用,set里面存的是string類型,多次的拷貝構造e會降低效率,不想改變就加上const即可for (const auto& e : strset){cout << e << " ";}cout << endl;return 0;
}
2.6 find和erase使用樣例

erase刪除成功就返回1,刪除失敗就返回0?

【erase+find+count】?
#include<iostream>
#include<set>using namespace std;int main()
{set<int> s = { 1,4,0,34,12,56 };for (auto e : s){cout << e << " ";}cout << endl;//1.利用迭代器進行刪除,刪除最小值s.erase(s.begin());for (auto e : s){cout << e << " ";}cout << endl;//2.直接輸入x,刪除xint x = 0;cin >> x;//erase的返回值幫助我們去判斷是否刪除成功int num = s.erase(x);if (num == 0){cout << x << "不存在!" << endl;}for (auto e : s){cout << e << " ";}cout << endl;//3.先查找再利用迭代器去刪除int y = 0;cin >> y;auto pos = s.find(y);if (pos != s.end())s.erase(pos);elsecout << "不存在!" << endl;for (auto e : s){cout << e << " ";}cout << endl;// 算法庫的查找 O(N),全部進行遍歷auto pos1 = find(s.begin(), s.end(), x);// set??實現的查找 O(logN),按照平衡二叉樹的特點進行尋找auto pos2 = s.find(x);// 利?count間接實現快速查找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()
{set<int> s = { 10,20,35 ,40 ,50 ,65 ,70 ,80 ,90 };for (int i = 1; i < 10; i++){s.insert(i * 10);}for (auto e : s){cout << e << " ";}cout << endl;// 實現查找到[itlow,itup)包含[30, 60]區間],注意[itlow,itup)左閉右開// 返回 >= 30auto itlow = s.lower_bound(30);// 返回 > 60auto itup = s.upper_bound(60);//刪除這段區間的值s.erase(itlow, itup);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}
2.7 multiset和set的差異

multiset和set的使用基本完全類似,主要區別點在于multiset?持值冗余,那么 insert/find/count/erase都圍繞著支持值冗余有所差異,具體參看下?的樣例代碼理解。

#include<iostream>
#include<set> using namespace std;int main()
{//相比set不同的是,multiset是排序,但是不去重multiset<int> s = { 1,4,3,4,6,4,8,3,0 };for (auto e : s){cout << e << " ";}cout << endl;//multiset相比于set不同的是,里面可以存在多個x,find查找中序里面的第一個xint x = 0;cin >> x;//返回的是pos位置的迭代器,返回的是中序里面的第一個xauto pos = s.find(x);while (pos != s.end() && *pos == x){cout << *pos << " ";++pos;}cout << endl;// 相比set不同的是,count會返回x的實際個數cout << s.count(x) << endl;//相?set不同的是,erase給值時會刪除所有的xs.erase(x);for (auto e : s){cout << e << " ";}cout << endl;return 0;
}
2.8?349. 兩個數組的交集 - 力扣(LeetCode)

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());// 因為set遍歷是有序的,有序值,依次?較// ?的++,相等的就是交集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;}
};
2.9?142. 環形鏈表 II - 力扣(LeetCode)

數據結構初階階段,我們通過證明?個指針從頭開始??個指針從相遇點開始?,會在??點相遇, 理解證明都會很?煩。這?我們使?set查找記錄解決?常簡單?便,這?體現了set在解決?些問題時的價值,完全是降維打擊。

快速判斷一個值在不在,下面類似的算法很有用

class Solution {
public:ListNode* detectCycle(ListNode* head) {set<ListNode*> s;ListNode* cur = head;while (cur){//如果cur在s.count的返回值是1,則表明帶環,返回值是0是插入即可if(s.count(cur))return cur;//入環節點elses.insert(cur);cur=cur->next;}return nullptr;}
};


三、map系列的使用

3.1 map和multimap參考文檔

<map> - C++ Reference

3.2 map類的介紹

map的聲明如下,Key就是map底層關鍵字的類型,T是map底層value的類型,set默認要求Key?持?于?較,如果不?持或者需要的話可以自行實現仿函數傳給第?個模版參數,map底層存儲數據的 內存是從空間配置器申請的。?般情況下,我們都不需要傳后兩個模版參數。map底層是用紅黑樹實現,增刪查改效率是 O(logN) ,迭代器遍歷是走的中序,所以是按key有序順序遍歷的。

3.3 pair類型介紹

map底層的紅?樹節點中的數據,使?pair(類模版)存儲鍵值對數據。

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));
}
3.4 map的構造

map的構造我們關注以下?個接?即可。

map的?持正向和反向迭代遍歷,遍歷默認按key的升序順序,因為底層是?叉搜索樹,迭代器遍歷? 的中序;?持迭代器就意味著?持范圍for,map?持修改value數據,不?持修改key數據,修改關鍵 字數據,破壞了底層搜索樹的結構。

// empty (1) ?參默認構造
explicit map(const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// range (2) 迭代器區間構造
template <class InputIterator>
map(InputIterator first, InputIterator last,const key_compare& comp = key_compare(),const allocator_type & = allocator_type());// copy (3) 拷?構造
map(const map& x);
// initializer list (5) initializer 列表構造
map(initializer_list<value_type> il,const key_compare& comp = key_compare(),const allocator_type& alloc = allocator_type());// 迭代器是?個雙向迭代器
iterator->a bidirectional iterator to const value_type// 正向迭代器
iterator begin();
iterator end();// 反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();
3.5 map的增刪查

map的增刪查關注以下?個接?即可: map增接?,插?的pair鍵值對數據,跟set所有不同,但是查和刪的接?只?關鍵字key跟set是完全類似的,不過find返回iterator,不僅僅可以確認key在不在,還找到key映射的value,同時通過迭代還可以修改value

Member types
key_type -> The first template parameter (Key)
mapped_type -> The second template parameter (T)
value_type -> pair<const key_type,mapped_type>// 單個數據插?,如果已經key存在則插?失敗,key存在相等value不相等也會插?失敗
pair<iterator,bool> insert (const value_type& val);// 列表插?,已經在容器中存在的值不會插?
void insert (initializer_list<value_type> il);// 迭代器區間插?,已經在容器中存在的值不會插?
template <class InputIterator>
void insert (InputIterator first, InputIterator last);// 查找k,返回k所在的迭代器,沒有找到返回end()
iterator find (const key_type& k);// 查找k,返回k的個數
size_type count (const key_type& k) const;// 刪除?個迭代器位置的值
iterator erase (const_iterator position);// 刪除k,k存在返回0,存在返回1
size_type erase (const key_type& k);// 刪除?段迭代器區間的值
iterator erase (const_iterator first, const_iterator last);// 返回?于等k位置的迭代器
iterator lower_bound (const key_type& k);// 返回?于k位置的迭代器
const_iterator lower_bound (const key_type& k) const;
3.6?構造遍歷及增刪查使?樣例
#include<iostream>
#include<map>
#include<string>using namespace std;int main()
{//轉換成多參數的直接構造kv1pair<string, string> kv1 = { "sky","天空" };//正常情況下是這樣的,先構造kv1對象,再用initializer list (5) initializer 列表構造//map<string, string>  dict = { kv1 };//這里是pair的多參數的構造的轉換,以前的單參數是直接構造,這里省略了上面的步驟map<string, string>  dict = { {"left","左邊"},{"right","右邊"},{"list","列表"},{"animal","動物"} };auto it = dict.begin();while (it != dict.end()){cout << (*it).first << ":"<<(*it).second << endl;// map的迭代基本都使?operator->,這?省略了?個->// 第?個->是迭代器運算符重載,返回pair*,第?個箭頭是結構指針解引?取pair數據//cout << it->first << ":"<<it->second << endl;//cout << it.operator->()->first << ":" << it->second << endl;it++;}cout << endl;//范圍for,為什么這里使用引用?for (const auto& e : dict){cout << e.first << ":" << e.second << endl;}cout << endl;
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// insert插?pair對象的4種?式,對?之下,最后?種最?便pair<string, string> kv2("one","一");dict.insert(kv2);//匿名對象去插入dict.insert(pair<string, string>("num", "數字"));//前兩個都是創建pair的對象,有名和匿名的區別dict.insert(make_pair("two", "二"));//多參數也支持隱式類型轉換dict.insert({ "three", "三" });for (const auto& e : dict){cout << e.first << ":" << e.second << endl;}cout << endl;//結構化綁定,將dict里面的值分別賦值給k和v,C++17才開始支持的for (const auto& [k,v] : dict){cout << k << ":" << v << endl;}//經典的key/value場景,通過一個值去找另一個值string str;while (cin >> str){auto ret = dict.find(str);if (ret != dict.end()){cout << "->" << ret->second << endl;}else{cout << "不存在!請重新輸入" << endl;}}return 0;
}

//修改map里面的second#include<iostream>
#include<map>
#include<string>using namespace std;int main()
{map<string, string>  dict = { {"left","左邊"},{"right","右邊"},{"list","列表"},{"animal","動物"} };//通過迭代器進行修改,但是僅能修改secondfor (auto& e : dict){e.second += "y";cout << e.second << endl;}cout << endl;//通過find進行修改auto ret = dict.find("left");ret->second = "左邊";for (const auto& e : dict){cout << e.first << ":" << e.second << endl;}return 0;
}
3.7?map的數據修改+map的迭代器和[ ]功能樣例

[ ]的底層是用insert實現的,我們先來了解insert?

前?我提到map?持修改mapped_type 數據,不?持修改key數據,修改關鍵字數據,破壞了底層搜索樹的結構。 map第?個?持修改的?式是通過迭代器,迭代器遍歷時或者find返回key所在的iterator修改,map 還有?個?常重要的修改接?operator[],但是operator[]不僅僅?持修改,還?持插?數據和查找數據,所以他是?個多功能復合接?需要注意從內部實現?度,map這?把我們傳統說的value值,給的是T類型,typedef為 mapped_type。?value_type是紅?樹結點中存儲的pair鍵值對值。?常使?我們還是習慣將這?的T映射值叫做value。

Member types
key_type -> The first template parameter (Key)
mapped_type -> The second template parameter (T)
value_type -> pair<const key_type,mapped_type>
// 查找k,返回k所在的迭代器,沒有找到返回end(),如果找到了通過iterator可以修改key對應的
mapped_type值
iterator find (const key_type& k);// ?檔中對insert返回值的說明
// The single element versions (1) return a pair, with its member pair::first
set to an iterator pointing to either the newly inserted element or to the
element with an equivalent key in the map. The pair::second element in the pair
is set to true if a new element was inserted or false if an equivalent key
already existed.// insert插??個pair<key, T>對象
// 1、如果key已經在map中,插?失敗,則返回?個pair<iterator,bool>對象,返回pair對象
first是key所在結點的迭代器,second是false// 2、如果key不在在map中,插?成功,則返回?個pair<iterator,bool>對象,返回pair對象
first是新插?key所在結點的迭代器,second是true// 也就是說?論插?成功還是失敗,返回pair<iterator,bool>對象的first都會指向key所在的迭代器
// 那么也就意味著insert插?失敗時充當了查找的功能,正是因為這?點,insert可以?來實現operator[]
// 需要注意的是這?有兩個pair,不要混淆了,?個是map底層紅?樹節點中存的pair<key, T>,另
?個是insert返回值pair<iterator,bool>pair<iterator,bool> insert (const value_type& val);
mapped_type& operator[] (const key_type& k);
// operator的內部實現
mapped_type& operator[] (const key_type& k)
{
// 1、如果k不在map中,insert會插?k和mapped_type默認值,同時[]返回結點中存儲
mapped_type值的引?,那么我們可以通過引?修改返映射值。所以[]具備了插?+修改功能
// 2、如果k在map中,insert會插?失敗,但是insert返回pair對象的first是指向key結點的
迭代器,返回值同時[]返回結點中存儲mapped_type值的引?,所以[]具備了查找+修改的功能
pair<iterator, bool> ret = insert({ k, mapped_type() });
iterator it = ret.first;
return it->second;
}

【應用1】?
#include<iostream>
#include<map>
#include<string>using namespace std;int main()
{map<string, string> dict;//不存在,插入{"insert",string()},value中插入的是string()的默認值dict["insert"];//不存在,成功插入,返回的是value的引用,可以完成修改dict["list"] = "列表";//修改dict["list"] = "列表,清單";//查找,已存在就返回已存在list結點迭代器中value的引用cout << dict["list"] << endl;return 0;
}
【應用2】
int main()
{// 利?find和iterator修改功能,統計?果出現的次數string arr[] = { "蘋果", "西?", "蘋果", "西?", "蘋果", "蘋果", "西?","蘋果", "?蕉", "蘋果", "?蕉" };map<string, int> countMap;for (const auto& str : arr){// 先查找?果在不在map中// 1、不在,說明?果第?次出現,則插?{?果, 1}// 2、在,則查找到的節點中?果對應的次數++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;}cout << endl;return 0;
}//根據上面學的知識,下面一句代碼就搞定上面代碼的場景,厲害!
int main()
{// 利?[]插?+修改功能,巧妙實現統計?果出現的次數string arr[] = { "蘋果", "西?", "蘋果", "西?", "蘋果", "蘋果", "西?","蘋果", "?蕉", "蘋果", "?蕉" };map<string, int> countMap;for (const auto& str : arr){// []先查找?果在不在map中// 1、不在,說明?果第?次出現,則插?{?果, 0},同時返回次數的引?,++?下就變成1次了// 2、在,則返回?果對應的次數++countMap[str]++;}for (const auto& e : countMap){cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}
3.8?multimap和map的差異

multimap和map的使?基本完全類似,主要區別點在于multimap?持關鍵值key冗余,那么 insert/find/count/erase都圍繞著?持關鍵值key冗余有所差異,這?跟set和multiset完全?樣,?如 find時,有多個key,返回中序第?個。其次就是multimap不?持[],因為?持key冗余,[]就只能?持插入了,不能?持修改。

3.9?138. 隨機鏈表的復制 - 力扣(LeetCode)

數據結構初階階段,為了控制隨機指針,我們將拷?結點鏈接在原節點的后?解決,后?拷?節點還得解下來鏈接,?常?煩。這?我們直接讓{原結點,拷?結點}建?映射關系放到map中,控制隨機指針會?常簡單?便,這?體現了map在解決?些問題時的價值,完全是降維打擊。

一開始不理解的,順著下面的代碼思路自己畫圖,當你畫到處理random代碼的時候你就會恍然大悟,泰褲辣!我菜還是得多練

class Solution {
public:Node* copyRandomList(Node* head) {map<Node*, Node*> nodeMap;Node* copyhead = nullptr, * copytail = nullptr;Node* cur = head;while (cur){if (copytail == nullptr){copyhead = copytail = new Node(cur->val);}else{copytail->next = new Node(cur->val);copytail = copytail->next;}// 原節點和拷?節點map kv存儲nodeMap[cur] = copytail;cur = cur->next;}// 處理randomcur = head;Node* copy = copyhead;while (cur){if (cur->random == nullptr){copy->random = nullptr;}else{copy->random = nodeMap[cur->random];}cur = cur->next;copy = copy->next;}return copyhead;}
};
3.10?692. 前K個高頻單詞 - 力扣(LeetCode)

本題?我們利?map統計出次數以后,返回的答案應該按單詞出現頻率由?到低排序,有?個特殊要求,如果不同的單詞有相同出現頻率,按字典順序排序。

解決思路1: ?排序找前k個單詞,因為map中已經對key單詞排序過,也就意味著遍歷map時,次數相同的單詞, 字典序?的在前?,字典序?的在后?。那么我們將數據放到vector中??個穩定的排序就可以實現上?特殊要求,但是sort底層是快排,是不穩定的,所以我們要?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> countMap;for (auto& e : words){countMap[e]++;}vector<pair<string, int>> v(countMap.begin(), countMap.end());// 仿函數控制降序stable_sort(v.begin(), v.end(), Compare());//sort(v.begin(), v.end(), Compare());// 取前k個vector<string> strV;for (int i = 0; i < k; ++i){strV.push_back(v[i].first);}return strV;}
};

解決思路2: 將map統計出的次數的數據放到vector中排序,或者放到priority_queue中來選出前k個。利?仿函數強?控制次數相等的,字典序?的在前?。

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> countMap;for (auto& e : words){countMap[e]++;}vector<pair<string, int>> v(countMap.begin(), countMap.end());// 仿函數控制降序,仿函數控制次數相等,字典序?的在前?sort(v.begin(), v.end(), Compare());// 取前k個vector<string> strV;for (int i = 0; i < k; ++i){strV.push_back(v[i].first);}return strV;}
};
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> countMap;for (auto& e : words){countMap[e]++;}// 將map中的<單詞,次數>放到priority_queue中,仿函數控制?堆,次數相同按照字典//序規則排序priority_queue<pair<string, int>, vector<pair<string, int>>, Compare>p(countMap.begin(), countMap.end());vector<string> strV;for (int i = 0; i < k; ++i){strV.push_back(p.top().first);p.pop();}return strV;}
};

完——


花曇り_佐藤千亜妃

現在聽到,依舊喜歡

至此結束——

我是云邊有個稻草人

期待與你的下一次相遇......

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/90110.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/90110.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/90110.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java 大視界 -- Java 大數據在智能交通自動駕駛車輛與周邊環境信息融合與決策中的應用(357)

Java 大視界 -- Java 大數據在智能交通自動駕駛車輛與周邊環境信息融合與決策中的應用&#xff08;357&#xff09;引言&#xff1a;正文&#xff1a;一、Java 構建的環境信息融合架構1.1 多傳感器數據實時關聯1.2 動態障礙物軌跡預測二、Java 驅動的決策系統設計2.1 緊急決策與…

單細胞轉錄組學+空間轉錄組的整合及思路

一、概念 首先還是老規矩&#xff0c;處理一下概念問題&#xff0c;好將之后的問題進行分類和區分 單細胞轉錄組&#xff1a;指在單個細胞水平上對轉錄組&#xff08;即細胞內所有轉錄出來的 RNA&#xff0c;主要是 mRNA&#xff09;進行研究的學科或技術方向&#xff0c;核心…

用Python實現神經網絡(五)

這一節告訴你如何用TensorFlow實現全連接網絡。安裝 DeepChem這一節&#xff0c;你將使用DeepChem 機器學習工具鏈進行實驗在網上可以找到 DeepChem詳細安裝指導。Tox21 Dataset作為我們的建模案例研究&#xff0c;我們使用化學數據庫。毒理學家很感興趣于用機器學習來預測化學…

ReasonFlux:基于思維模板與分層強化學習的高效推理新范式

“以結構化知識壓縮搜索空間&#xff0c;讓輕量模型實現超越尺度的推理性能” ReasonFlux 是由普林斯頓大學與北京大學聯合研發的創新框架&#xff08;2025年2月發布&#xff09;&#xff0c;通過 結構化思維模板 與 分層強化學習&#xff0c;顯著提升大語言模型在復雜推理任務…

PHP與Web頁面交互:從基礎表單到AJAX實戰

文章目錄 PHP與Web頁面交互:從基礎到高級實踐 1. 引言 2. 基礎表單處理 2.1 HTML表單與PHP交互基礎 2.2 GET與POST方法比較 3. 高級交互技術 3.1 AJAX與PHP交互 3.2 使用Fetch API進行現代AJAX交互 4. 文件上傳處理 5. 安全性考量 5.1 常見安全威脅與防護 5.2 數據驗證與過濾 …

OpenCV基本的圖像處理

參考資料&#xff1a; 參考視頻 視頻參考資料:鏈接: https://pan.baidu.com/s/1_DJTOerxpu5_dSfd4ZNlAA 提取碼: 8v2n 相關代碼 概述&#xff1a; 因為本人是用于機器視覺的圖像處理&#xff0c;所以只記錄了OpenCV的形態學操作和圖像平滑處理兩部分 形態學操作&#xff1a;…

Git 與 GitHub 學習筆記

本文是一份全面的 Git 入門指南,涵蓋了從環境配置、創建倉庫到日常分支管理和與 GitHub 同步的全部核心操作。 Part 1: 初始配置 (一次性搞定) 在開始使用 Git 之前,需要先配置好你的電腦環境。(由于網絡的原因,直接使用https的方式拉取倉庫大概率是失敗的,故使用ssh的方…

文件系統-文件存儲空間管理

文件存儲空間管理的核心是空閑塊的組織、分配與回收&#xff0c;確保高效利用磁盤空間并快速響應文件操作&#xff08;創建、刪除、擴展&#xff09;。以下是三種主流方法&#xff1a;1. 空閑表法&#xff08;連續分配&#xff09;原理&#xff1a;類似內存動態分區&#xff0c…

python爬蟲實戰-小案例:爬取蘇寧易購的好評

一、項目背景與價值1 為什么爬取商品好評&#xff1f; 消費者洞察&#xff1a;分析用戶真實反饋&#xff0c;了解產品優缺點 市場研究&#xff1a;監測競品評價趨勢&#xff0c;優化產品策略二.實現代碼from selenium import webdriver from selenium.webdriver.edge.options i…

Spring Boot環境搭建與核心原理深度解析

一、開發環境準備 1.1 工具鏈選擇 JDK版本&#xff1a;推薦使用JDK 17&#xff08;LTS版本&#xff09;&#xff0c;與Spring Boot 3.2.5完全兼容&#xff0c;支持虛擬線程等JDK 21特性可通過配置啟用構建工具&#xff1a;Maven 3.8.6&#xff08;配置阿里云鏡像加速依賴下載…

Java自動拆箱機制

在黑馬點評項目中&#xff0c;提到了一個細節&#xff0c;就是Java的自動拆箱機制&#xff0c;本文來簡單了解一下。Java 的??自動拆箱機制&#xff08;Unboxing&#xff09;??是一種編譯器層面的語法糖&#xff0c;用于簡化??包裝類對象??&#xff08;如 Integer、Boo…

哈希算法(Hash Algorithm)

哈希算法&#xff08;Hash Algorithm&#xff09;是一種將任意長度的數據映射為固定長度的哈希值&#xff08;Hash Value&#xff09;的算法&#xff0c;廣泛應用于密碼學、數據完整性驗證、數據結構&#xff08;如哈希表&#xff09;和數字簽名等領域。&#x1f9e0; 一、哈希…

黑馬點評使用Apifox進行接口測試(以導入更新店鋪為例、詳細圖解)

目錄 一、前言 二、手動完成接口測試所需配置 三、進行接口測試 一、前言 在學習黑馬點評P39實現商鋪緩存與數據庫的雙寫一致課程中&#xff0c;老師使用postman進行了更新店鋪的接口測試。由于課程是22年的&#xff0c;按照我從24年JavaWebAI課程所學習使用的Apifox內部其實…

Ubuntu 虛擬機配置 與Windows互傳文件

在VMware中為Ubuntu虛擬機設置共享文件夾 設置共享文件夾可以傳遞大量文件 在VMware的設置中打開共享文件夾功能&#xff0c;并設置共享文件夾的目錄。 點擊添加后&#xff0c;選擇一個電腦上的文件夾&#xff0c;這個文件夾最好是新建的空的。 完成后在“文件夾”列表中就…

機器學習對詞法分析、句法分析、淺層語義分析的積極影響

機器學習在自然語言處理的詞法、句法及淺層語義分析中產生了革命性影響&#xff0c;顯著提升了各任務的精度和效率。以下是具體影響及實例說明&#xff1a;??一、詞法分析??1. ??中文分詞????提升歧義消解能力??&#xff1a;傳統方法依賴規則或統計&#xff0c;但深…

初學者STM32—USART

一、簡介USART&#xff08;Universal Synchronous/Asynchronous Receiver/Transmitter&#xff0c;通用同步/異步收發器&#xff09;是一種常見的串行通信協議&#xff0c;廣泛應用于微控制器、傳感器、模塊和其他電子設備之間的數據傳輸。本節課主要學習USART的基本結構以及其…

A316-V71-Game-V1:虛擬7.1游戲聲卡評估板技術解析

引言 隨著游戲產業的蓬勃發展&#xff0c;沉浸式音頻體驗成為提升游戲體驗的關鍵因素。本文將介紹一款專為游戲音頻設計的評估板——A316-V71-Game-V1&#xff0c;這是一款基于XMOS XU316技術的虛擬7.1游戲聲卡評估平臺。產品概述 A316-V71-Game-V1是一款專為虛擬7.1游戲聲卡設…

小白成長之路-部署Zabbix7

文章目錄一、概述二、案例三、第二臺虛擬機監控總結一、概述 二、案例 實驗開始前&#xff1a; systemctl disable --now firewalld setenforce 0 Rocky9.4部署Zabbix7 一、配置安裝源 rpm -Uvh https://repo.zabbix.com/zabbix/7.0/rocky/9/x86_64/zabbix-release-7.0-5.el…

飛書非正常顯示與權限問題解決方案

可能是本地緩存導致的&#xff0c;讓員工參考以下方法操作下&#xff1a;看不懂下面的建議刪除飛書再重新安裝&#xff1b;博主就遇到過版本低的原因&#xff0c;試過下面方面都不行。結果就是刪除重新安裝&#xff0c;博主是mac電腦。Windows 系統關閉飛書。如果不能關閉&…

第十八節:第八部分:java高級:動態代理設計模式介紹、準備工作、代碼實現

程序為什么需要代理以及代理長什么樣如何為java對象創建一個代理對象代碼&#xff1a; BigStar類 package com.itheima.day11_Proxy;public class BigStar implements Star {private String name;public BigStar(String name) {this.name name;}public String sing(String nam…