传统数组的局限性:
Set和Map的优势:
基本操作示例:
#include <set>
#include <iostream>
using namespace std;
int main() {
set<int> s;
// 插入元素
s.insert(3);
s.insert(1);
s.insert(4);
s.insert(1); // 重复元素,不会插入
// 遍历(自动排序)
for (int x : s) {
cout << x << " "; // 输出:1 3 4
}
// 查找元素
if (s.find(3) != s.end()) {
cout << "找到3";
}
return 0;
}
常用操作总结:
insert(element)erase(element)find(element)size()empty()clear()高级操作:
lower_bound(), upper_bound()begin(), rbegin()count(element)基本操作示例:
#include <map>
#include <iostream>
using namespace std;
int main() {
map<string, int> m;
// 插入键值对
m["Alice"] = 95;
m["Bob"] = 88;
m["Charlie"] = 92;
// 遍历(按键排序)
for (auto& p : m) {
cout << p.first << ": "
<< p.second << endl;
// 输出:Alice: 95, Bob: 88, Charlie: 92
}
// 查找键
if (m.find("Alice") != m.end()) {
cout << "Alice的成绩:" << m["Alice"] << endl;
}
return 0;
}
常用操作总结:
insert({key, value}) 或 map[key] = valuemap[key] 或 map.at(key)erase(key)find(key)size()empty()高级特性:
有序性特性:
lower_bound(), upper_bound()begin(), rbegin()稳定性特性:
基本操作示例:
#include <unordered_set>
#include <iostream>
using namespace std;
int main() {
unordered_set<int> us;
// 插入元素
us.insert(3);
us.insert(1);
us.insert(4);
us.insert(1); // 重复元素,不会插入
// 遍历(无序)
for (int x : us) {
cout << x << " "; // 顺序不确定
}
// 查找元素(平均O(1))
if (us.find(3) != us.end()) {
cout << "找到3";
}
return 0;
}
常用操作总结:
insert(element)erase(element)find(element)size()empty()clear()性能特点:
适用场景:
基本操作示例:
#include <unordered_map>
#include <iostream>
using namespace std;
int main() {
unordered_map<string, int> um;
// 插入键值对
um["Alice"] = 95;
um["Bob"] = 88;
um["Charlie"] = 92;
// 遍历(无序)
for (auto& p : um) {
cout << p.first << ": "
<< p.second << endl;
// 顺序不确定
}
// 查找键(平均O(1))
if (um.find("Alice") != um.end()) {
cout << "Alice的成绩:" << um["Alice"] << endl;
}
return 0;
}
常用操作总结:
insert({key, value}) 或 um[key] = valueum[key] 或 um.at(key)erase(key)find(key)size()empty()哈希表特性:
哈希冲突的概念:
常见的冲突解决方法:
// 自定义哈希函数示例
struct MyHash {
size_t operator()(const string& s) const {
return hash<string>()(s);
}
};
unordered_set<string, MyHash> custom_set;
| 操作 | Sorted类型 | Hash类型 | 选择建议 |
|---|---|---|---|
| 插入 | 平均 |
大数据量选Hash | |
| 删除 | 平均 |
频繁操作选Hash | |
| 查找 | 平均 |
快速查找选Hash | |
| 遍历 | 两者相当 | ||
| 最小/最大 | 不支持 | 需要有序选Sorted | |
| 范围查询 | 支持 | 不支持 | 需要范围选Sorted |
选择Sorted类型的场景:
具体应用示例:
选择Hash类型的场景:
具体应用示例:
CESE竞赛特点:
USACO竞赛特点:
问题描述:
给定n个整数,统计去重后有多少个不同的数。
输入格式:
第一行一个整数n,第二行n个整数
输出格式:
不同整数的个数
解题思路:
使用set自动去重,然后输出size
#include <iostream>
#include <set>
using namespace std;
int main() {
int n, x;
set<int> s;
cin >> n;
for (int i = 0; i < n; i++) {
cin >> x;
s.insert(x);
}
cout << s.size() << endl;
return 0;
}
问题描述:
统计一篇文章中每个单词出现的次数。
输入格式:
多行文本,以EOF结束
输出格式:
每个单词及其出现次数,按字典序输出
解题思路:
使用map存储单词到次数的映射
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> wordCount;
string word;
while (cin >> word) {
wordCount[word]++;
}
for (auto& p : wordCount) {
cout << p.first << ": " << p.second << endl;
}
return 0;
}
问题描述:
多次查询两个节点的最近公共祖先。
解题思路:
使用map存储每个节点的父节点信息
#include <iostream>
#include <map>
#include <set>
using namespace std;
map<int, int> parent; // 子节点->父节点映射
int findLCA(int a, int b) {
set<int> path;
// 记录a到根节点的路径
while (a != 0) {
path.insert(a);
a = parent[a];
}
// 找到b路径上与a路径的交点
while (b != 0) {
if (path.find(b) != path.end()) {
return b;
}
b = parent[b];
}
return 0;
}
问题描述:
实现LRU缓存机制,支持get和put操作。
解题思路:
使用unordered_map快速查找,结合双向链表维护访问顺序
#include <unordered_map>
#include <list>
using namespace std;
class LRUCache {
private:
int capacity;
list<pair<int, int>> cache;
unordered_map<int, list<pair<int, int>>::iterator> map;
public:
LRUCache(int capacity) : capacity(capacity) {}
int get(int key) {
if (map.find(key) == map.end()) return -1;
// 移动到链表头部
cache.splice(cache.begin(), cache, map[key]);
return map[key]->second;
}
void put(int key, int value) {
if (map.find(key) != map.end()) {
// 更新值并移动到头部
map[key]->second = value;
cache.splice(cache.begin(), cache, map[key]);
} else {
// 插入新元素
if (cache.size() == capacity) {
// 删除尾部元素
map.erase(cache.back().first);
cache.pop_back();
}
cache.emplace_front(key, value);
map[key] = cache.begin();
}
}
};
问题描述:
实现支持变量的表达式求值。
解题思路:
使用map存储变量名到值的映射
#include <iostream>
#include <map>
#include <string>
#include <sstream>
using namespace std;
map<string, int> variables;
int evaluate(const string& expr) {
istringstream iss(expr);
string token;
int result = 0;
char op = '+';
while (iss >> token) {
if (token == "+" || token == "-" || token == "*" || token == "/") {
op = token[0];
} else {
int value;
if (isdigit(token[0])) {
value = stoi(token);
} else {
value = variables[token];
}
switch (op) {
case '+': result += value; break;
case '-': result -= value; break;
case '*': result *= value; break;
case '/': result /= value; break;
}
}
}
return result;
}
题目1:数组去重
题目2:词频统计
题目3:缓存模拟
题目4:最近公共祖先
题目5:表达式求值
题目6:LRU缓存
Sorted类型核心要点:
Hash类型核心要点:
选择原则总结:
基础知识掌握:
竞赛能力提升:
实践项目推荐:
进阶学习方向:
在线文档资源:
竞赛平台推荐:

这个讲义使用了Awesome Marp主题的蓝色风格。 内容针对竞赛选手设计,注重基础概念和实际应用。