You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

std::unordered_map异常行为排查:LeetCode题解中的奇怪问题

关于std::unordered_map在「最小必要团队」问题中的异常行为解释

问题1:移除reserve导致错误的原因

std::unordered_map底层基于哈希表实现,当存储的元素数量超过负载因子×桶数的阈值时,会触发rehash操作——重新分配更大的桶空间,将所有元素重新哈希到新桶中。这个过程会让此前所有的迭代器(包括正在遍历的迭代器)直接失效,变成野指针。

如果你的代码在遍历teams的同时进行插入/修改操作,且未处理迭代器失效的问题,那么当rehash发生时,程序会出现逻辑错误:比如跳过某个状态的处理、访问错误的内存,最终计算出错误的团队组合。

调用teams.reserve(1 << TOTAL_REQ_SKILLS)是提前分配足够的桶空间,确保后续所有插入操作都不会触发rehash,从根源上避免了迭代器失效的问题,因此代码能正确运行。

问题2:两种初始化方式的差异

虽然两种方式最终teams中都包含{0, 空vector},但底层构造过程的差异导致了后续rehash触发时机不同:

  • 列表初始化std::unordered_map<int, std::vector<int>> teams = { { 0, {} } };:直接构造包含初始键值对的map,此时map的桶数会被设置为刚好容纳初始元素的最小数量(比如部分编译器会设为1)。后续插入元素时,很快就会达到负载因子阈值触发rehash,刚好撞上你代码中依赖迭代器的关键逻辑,导致失效引发错误。
  • 默认构造后赋值unordered_map<int, vector<int>> teams; teams[0] = {};:默认构造的unordered_map会有一个默认初始桶数(比如8),插入key=0时桶数足够,不会触发rehash。后续插入元素时,需要积累更多元素才会触发rehash,或者触发时机不在你代码依赖迭代器的路径上,因此即使没有reserve,代码也能正常运行。

本质上这不是unordered_map的异常行为,而是你的代码存在迭代器失效的隐患,两种初始化方式只是改变了隐患暴露的时机。正确的做法要么提前reserve足够空间,要么在遍历并修改map时,避免使用失效的迭代器(比如每次插入后重新获取迭代器)。

内容的提问来源于stack exchange,提问作者Ashutosh Aswal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 23:02:31