1. 平衡二叉搜索树 — std::set / std::map
底层数据结构
红黑树(自平衡二叉搜索树),元素按键值有序存储。
时间复杂度
- 插入、删除、查找:O(log n) 平均 & 最坏
- 遍历有序:O(n)
- 前驱后继(lower_bound/upper_bound):O(log n)
空间复杂度
- O(n),每个节点额外存储左右孩子指针、父节点指针、颜色(通常 3 个指针 + 1 字节),内存开销较大。
使用条件
- 需要元素按 key 有序(按序遍历、输出排序结果)
- 需要频繁的范围查询(比 x 大的最小元素、比 x 小的最大元素)
- 迭代器不能因插入而失效(有稳定迭代器需求)
- 元素类型没有合适的哈希函数,或担心哈希被卡
- 数据规模 ≤ 2×10⁵ 且 O(log n) 完全够用
2. 哈希表 — std::unordered_set / std::unordered_map
底层数据结构
开链法(Separate Chaining)哈希表。由一个桶数组(动态扩缩容)和链表/红黑树(当桶内冲突过多时 C++11 后可能转红黑树)构成。
时间复杂度
- 插入、删除、查找:平均 O(1),最坏 O(n)(大量冲突退化为链表)
- 不支持顺序查询
空间复杂度
- O(n),但常数较大(桶数组 + 每个节点的指针/哈希值存储),负载因子默认约 1.0,内存占用通常大于红黑树。
使用条件
- 只需要快速判存在,不关心顺序
- 数据分布较均匀,哈希冲突概率低
- 没有范围查询需求
- 作为通用哈希表,适用于绝大多数情况,竞赛中极少被故意卡(int/string 等默认哈希很安全)
3. 直接寻址数组 — bool arr[128] / std::array<bool, N>
底层数据结构
把 key 直接当作数组下标,相当于“哈希函数为恒等映射”。每个位置存储一个 bool 或计数。
时间复杂度
- 插入、删除、查找:严格 O(1),常数极小
- “哈希函数”就是取下标,零冲突
空间复杂度
- O(M),M 为 key 域的大小(例如字母大小写共 128,或数字范围 10⁷)。
- 如果 key 域很大但实际存储元素稀疏,空间浪费严重。
使用条件
- key 的范围很小且连续/可枚举(如 ASCII 字符、小范围整数)
- 追求极致速度,同时内存放得下整个域
- 这是 “用空间换时间”的终极形态,也是竞赛中处理字符集问题的最优解
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param jewels string字符串
* @param stones string字符串
* @return int整型
*/
int numJewelsInStones(string jewels, string stones) {
array<bool,128> isJewel{};
for(const auto& jewel:jewels) isJewel[jewel]=true;
int cnt=0;
for(const auto& stone:stones) cnt+=isJewel[stone];
return cnt;
}
};

京公网安备 11010502036488号