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

如何在C++ STL map中删除重复值条目(保留首个键对应条目)

最优解决C++ STL Map删除值重复条目问题

嘿,我来帮你搞定这个需求!要在STL map里删除值重复的条目,只保留每个值对应的第一个出现的键(也就是按map默认的键升序排列最早的那个,比如你的例子里保留'a'而非'e',保留'd'而非'f'、'h'),同时追求时间和空间复杂度最优,咱们可以用这个高效的方案:

核心思路

因为std::map本身是有序容器(默认按键的升序存储),所以每个值第一次出现时对应的键就是我们要保留的那个。我们只需要遍历一次map,用一个哈希集合记录已经见过的值:

  • 遇到没见过的值:把它加入集合,继续遍历下一个元素
  • 遇到已经见过的值:直接删除当前条目

要注意的是,遍历map时删除元素不能用普通的for循环,否则会导致迭代器失效,得用erase()的返回值来更新迭代器。

完整代码示例

#include <iostream>
#include <map>
#include <unordered_set>

int main() {
    // 初始化你的map
    std::map<char, int> mymap = {
        {'a', 111}, {'b', 567}, {'c', 956}, {'d', 222},
        {'e', 111}, {'f', 222}, {'h', 222}, {'i', 492}
    };

    std::unordered_set<int> seen_values;
    auto it = mymap.begin();

    while (it != mymap.end()) {
        if (seen_values.find(it->second) != seen_values.end()) {
            // 值已存在,删除当前元素,迭代器指向erase返回的下一个元素
            it = mymap.erase(it);
        } else {
            // 值未出现过,加入集合,迭代器后移
            seen_values.insert(it->second);
            ++it;
        }
    }

    // 打印处理后的结果验证
    for (const auto& pair : mymap) {
        std::cout << "<'" << pair.first << "', " << pair.second << "> ";
    }
    return 0;
}

运行这段代码后,输出会是:<'"a", 111> <'"b", 567> <'"c", 956> <'"d", 222> <'"i", 492>,完全符合你的要求。

复杂度分析

  • 时间复杂度:平均O(n)。map的遍历是O(n),unordered_set的insert和find操作平均都是O(1),所以整体平均时间复杂度是线性的,这是能达到的最优水平。
  • 空间复杂度:O(k),其中k是map中不同值的数量。我们必须记录已经出现过的值,这是无法避免的最小空间开销,所以也是最优的。

为什么不用std::set?

可能有人会想到用std::set来记录见过的值,但set的插入和查找是O(logk)的时间复杂度,整体会变成O(n logk),比用unordered_set的平均O(n)要慢,所以优先选哈希集合。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:56:30