文章目录
1. set的使用
set是Key模型的二叉搜索树,它不仅能排序还能去重,底层实际上是用红黑树实现的。
注意:set的普通迭代器和const迭代器都不支持对Key的修改。
因为源码用的都是const_iterator。
1.1 插入
void test_set1()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
// 排序 + 去重
set<int>::iterator it = s.begin();
while (it != s.end())
{
//*it = 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
1.2 查找
erase得配合find使用。find如果没找到会返回end。set.find是按照二叉搜索树的性质来查找,时间复杂度是O(1)。而算法库里的find是暴力查找,时间复杂度是O(n)。
void test_set2()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
set<int>::iterator pos = s.find(20); // O(logN)
if (pos != s.end())
{
cout << "set.find找到了" << endl;
}
pos = find(s.begin(), s.end(), 2); // O(N)
if (pos != s.end())
{
cout << "find找到了" << endl;
}
}
1.3 删除
eras是从集合容器中移除单个元素或一组元素[first,last)。
如果没有找到pos就删除会出问题。所以删除时要加条件判断。而如果是直接用一个值去删除比如s.erase(3),编译器会自己去调用find,如果在就删除(返回删除的个数),不在就不会做任何事情(删除失败返回0)。
void test_set3()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
cout << s.erase(3) << endl;
cout << s.erase(30) << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
set<int>::iterator pos = s.find(3);
if (pos != s.end())
s.erase(pos);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
/*int x;
while (cin >> x)
{
set<int>::iterator pos = s.find(x);
if (pos != s.end())
{
s.erase(pos);
cout << "删除" << x << "成功" << endl;
}
else
{
cout << x << "不在set中" << endl;
}
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}*/
// count在容器中搜索与val相等的元素,并返回匹配的数量。
// count是为了支持multiset版本的set
// 对于普通set而言,因为集合容器中的所有元素都是唯一的,所以函数只能返回1(如果找到了元素)或0(否则)。
if (s.count(5))
{
cout << "5在" << endl;
}
if (s.find(5) != s.end())
{
cout << "5在" << endl;
}
}
1.4 lower_bound
void test_set4()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(7);
s.insert(9);
// 返回>= val得位置迭代器 3返回3位置 6 返回7位置
/*set<int>::iterator lowIt = s.lower_bound(3); 存在
lowIt = s.lower_bound(6); 不存在*/
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 要求删除>=x的所有值
int x;
cin >> x;
set<int>::iterator lowIt = s.lower_bound(x);
s.erase(lowIt, s.end());
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
1.5 upper_bound
因为erase从集合容器中移除单个元素或一组元素([first,last)])。
void test_set5()
{
set<int> s;
s.insert(4);
s.insert(5);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(7);
s.insert(9);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 返回>x位置的迭代器 -》 都是返回 7位置的迭代器
//set<int>::iterator upIt = s.upper_bound(5); // 存在
//upIt = s.upper_bound(6); // 不存在
// 删除x <= <= y的区间 删除 [x,y]
// 因为erase的区间是[first,last)
int x, y;
cin >> x >> y;
auto leftIt = s.lower_bound(x); // [
auto rightIt = s.upper_bound(y); // )
// 输入3 7区间为[3,9)包含[3,7]
s.erase(leftIt, rightIt);
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
}
1.6 multiset
multiset用法和set一样,唯一不同是允许键值冗余。排序不去重。
这里count的作用就体现出来了。
void test_set6()
{
multiset<int> s;
s.insert(4);
s.insert(5);
s.insert(2);
s.insert(1);
s.insert(1);
s.insert(3);
s.insert(2);
s.insert(1);
s.insert(3);
s.insert(3);
s.insert(3);
s.insert(3);
// 排序
set<int>::iterator it = s.begin();
while (it != s.end())
{
//*it = 10;
cout << *it << " ";
++it;
}
cout << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
cout << s.count(1) << endl;
cout << s.erase(1) << endl;
for (auto e : s)
{
cout << e << " ";
}
cout << endl;
// 多个x的话,find返回中序第一个x
auto pos = s.find(3);
while (pos != s.end())
{
cout << *pos << " ";
++pos;
}
cout << endl;
}
2. 两个数组的交集
3. map的使用
map是KV模型的二叉搜索树。
3.1 插入及其遍历
插入的是一个键值对,返回的也是一个键值对,iterator就是指向value_type的指针。
void test_map1()
{
map<string, string> dict;
// pair构造函数
dict.insert(pair<string, string>("sort", "排序"));
pair<string, string> kv("insert", "插入");
dict.insert(kv);
// make_pair函数模板自动推导类型
dict.insert(make_pair("left","左边"));
// C++11 再讲
//dict.insert({ "right", "右边" });
// 遍历
//map<string, string>::iterator it = dict.begin();
auto it = dict.begin();
while (it != dict.end())
{
//cout << *it << " "; // it->operator*()
//cout << (*it).first << ":" << (*it).second << endl;
cout << it->first << ":" << it->second << endl;
++it;
}
cout << endl;
for (const auto& kv : dict)
{
cout << kv.first << ":" << kv.second << endl;
}
}
3.2 统计水果出现次数
void test_map2()
{
string arr[] = { "苹果", "西瓜", "苹果", "西瓜", "苹果", "苹果", "西瓜", "苹果", "香蕉", "苹果", "香蕉" };
/*map<string, int> countMap;
for (auto& str : arr)
{
map<string, int>::iterator it = countMap.find(str);
if (it != countMap.end())
{
it->second++;
}
else
{
countMap.insert(make_pair(str, 1));
}
}*/
//map<string, int> countMap;
//for (auto& str : arr)
//{
// //pair<map<string, int>::iterator, bool> ret = countMap.insert(make_pair(str, 1));
// auto ret = countMap.insert(make_pair(str, 1));
// if (ret.second == false)
// {
// ret.first->second++;
// }
//}
map<string, int> countMap;
for (auto& str : arr)
{
countMap[str]++;
}
for (const auto& kv : countMap)
{
cout << kv.first << ":" << kv.second << endl;
}
}
insert单元素版本(1)返回一个元素对pair,pair::first被设置为一个迭代器,指向新插入的元素或映射中具有相同键值的元素。 如果插入了新元素,则pair::second设置为true;如果已经存在等价的键,则设置为false。
3.3 operator[]
multimap不支持operator[],因为一个key对应多个value。
3. 前k个高频单词
class Solution {
public:
typedef map<string,int>::iterator CountIter;
struct IterCompare
{
bool operator()(CountIter it1, CountIter it2)
{
return it1->second > it2->second;
}
};
vector<string> topKFrequent(vector<string>& words, int k) {
//按key排好序且统计对应的出现次数
map<string,int> countMap;
for(auto& str : words)
{
countMap[str]++;
}
//将map数据节点的迭代器放入vector
vector<CountIter> v;
CountIter it = countMap.begin();
while(it != countMap.end())
{
v.push_back(it);
++it;
}
//因为stable_sort只支持随机迭代器且是稳定的排序
//按出现次数排序,如果次数相同按照字典序排序
stable_sort(v.begin(), v.end(), IterCompare());
//录入排序好的结果--单词
vector<string> ret;
for(size_t i = 0; i < k; ++i)
{
ret.push_back(v[i]->first);
}
return ret;
}
};
第二种方法:
class Solution {
public:
vector<string> topKFrequent(vector<string>& words, int k) {
//按key排好序且统计对应的出现次数
map<string,int> countMap;
for(auto& str : words)
{
countMap[str]++;
}
//再用multimap按出现次数排序,排降序
//multimap遇到相等的值会插入到右边
multimap<int,string,great<int>> sortMap;
for(auto& kv : countMap)
{
sortMap.insert(make_pair(kv.second, kv.first));
}
//录入排序好的结果--单词
vector<string> ret;
auto it = sortMap.begin();
for(size_t i = 0; i < k; ++i)
{
ret.push_back(it->second);
++it;
}
return ret;
}
};
//再用multimap按出现次数排序,排降序
//multimap遇到相等的值会插入到右边
multimap<int,string,great<int>> sortMap;
for(auto& kv : countMap)
{
sortMap.insert(make_pair(kv.second, kv.first));
}
//录入排序好的结果--单词
vector<string> ret;
auto it = sortMap.begin();
for(size_t i = 0; i < k; ++i)
{
ret.push_back(it->second);
++it;
}
return ret;
}
};