LeetCode 两数之和 unordered_map 哈希表

这篇博客介绍了如何利用哈希表在给定数组中高效地找到和为目标值的两个整数的下标。通过遍历数组,将每个元素及其下标存入哈希表,然后检查目标值减去当前元素是否已存在于哈希表中,从而避免了二次遍历,提高了查找效率。示例展示了不同输入情况下的解决方案。

两数之和

  1. 两数之和
    给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
    你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
    你可以按任意顺序返回答案。
    示例 1:
    输入:nums = [2,7,11,15], target = 9
    输出:[0,1]
    解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
    示例 2:
    输入:nums = [3,2,4], target = 6
    输出:[1,2]
    示例 3:
    输入:nums = [3,3], target = 6
    输出:[0,1]

在这里插入图片描述

代码:

class Solution {
public:
    vector<int> twoSum(vector<int>& nums, int target) {
        unordered_map<int, int> hashmap;
        //map<int,int> hashmap; 
        for(int i=0;i<nums.size();i++){
        	//if(hashmap.find(target-nums[i])!=hashmap.end() && hashmap[target-nums[i]] != i)
            if(hashmap.find(target-nums[i])!=hashmap.end())
                return {i, hashmap[target-nums[i]]};
            else
                hashmap[nums[i]] = i;
        }
        return {};
    }
};
<think>嗯,用户想了解C++中unordered_map在算法中的应用及示例代码。首先,我需要回顾一下unordered_map的基本概念和它在STL中的特点。unordered_map是基于哈希表实现的,提供平均O(1)的查找、插入和删除操作,这与map的有序性不同,后者使用红黑树实现,操作是O(log n)的。 接下来,我需要整理几个典型的应用场景。比如统计词频,这在处理字符串或文本数据时很常见。这里可以举一个统计字符串中各字符出现次数的例子,用unordered_map来存储键值对,键是字符,值是出现次数。然后遍历字符串,对每个字符进行计数。 然后是作为辅助数据结构,比如两数之和问题。这个问题需要快速查找目标元素是否存在,使用unordered_map可以存储已经遍历过的元素及其索引,这样在每次计算差值时,可以快速判断差值是否存在于map中,从而找到符合条件的两个数。 还有图算法中的应用,比如邻接表。图的节点之间的连接关系可以用unordered_map来存储,键是节点,值是与该节点相连的其他节点列表。这样在遍历图的时候可以高效地访问邻接节点。 另外,可能需要提到性能优化方面,比如选择合适的哈希函数。特别是当键是自定义类型时,需要提供哈希函数和相等比较函数。例如,如果键是一个自定义的类,可能需要特化哈希模板,或者传递自定义的哈希函数给unordered_map。 然后,需要给出每个应用场景的示例代码。比如在统计词频时,代码可能包括插入元素、遍历字符串,并更新map中的值。在两数之和问题中,代码需要遍历数组,检查差值是否存在,并存储当前元素和索引。 还要注意代码的正确性,比如在C++中使用范围for循环遍历unordered_map,使用find方法查找元素,以及处理冲突的方法,比如开放定址法中的二次探测,虽然具体的实现可能隐藏在STL库内部,但用户可能需要了解这些机制对性能的影响。 此外,用户可能想知道如何在实际项目中使用unordered_map,比如如何初始化,如何插入元素,如何查找和删除。可以引用提供的参考内容,比如使用区间构造函数从vector初始化unordered_map,或者自定义哈希函数来处理字符串等特殊类型。 最后,可能需要提醒用户注意unordered_map的局限性,比如哈希冲突可能导致性能下降,以及在需要有序存储时应该选择map而不是unordered_map。同时,可以提到C++11之后的标准中对unordered_map的支持情况,以及不同编译器可能实现的差异。 总结一下,回答需要涵盖unordered_map的基本应用场景,每个场景的示例代码,性能优化的方法,以及相关的注意事项。引用提供的参考资料中的例子,比如初始化方法、自定义哈希函数和冲突解决策略,来增强回答的权威性和详细性。</think>### C++ unordered_map在算法中的应用及示例 unordered_map作为基于哈希表的关联容器,在算法中常用于快速查找、去重统计和构建映射关系。其$O(1)$平均时间复杂度特性使其在以下场景中表现优异: --- #### 一、词频统计(字符串处理) 统计字符串中各字符出现次数: ```cpp #include <unordered_map> #include <string> void count_chars(const std::string& s) { std::unordered_map<char, int> freq; for (char c : s) { freq[c]++; // 自动初始化值为0 } // 输出统计结果 for (const auto& pair : freq) { std::cout << pair.first << ": " << pair.second << "\n"; } } ``` 此方法时间复杂度为$O(n)$,空间复杂度$O(k)$(k为不同字符数)[^1] --- #### 二、两数之和(查找优化) LeetCode经典问题的高效解法: ```cpp #include <vector> #include <unordered_map> std::vector<int> twoSum(const std::vector<int>& nums, int target) { std::unordered_map<int, int> seen; // 值->索引映射 for (int i = 0; i < nums.size(); ++i) { int complement = target - nums[i]; if (seen.count(complement)) { return {seen[complement], i}; } seen[nums[i]] = i; } return {}; } ``` 通过哈希表将查找时间从$O(n)$降为$O(1)$,整体时间复杂度优化至$O(n)$[^2] --- #### 三、图算法(邻接表存储) 构建图结构的高效表示: ```cpp #include <unordered_map> #include <list> class Graph { private: std::unordered_map<int, std::list<int>> adjList; public: void addEdge(int src, int dest) { adjList[src].push_back(dest); adjList[dest].push_back(src); // 无向图 } }; ``` 此结构支持$O(1)$时间复杂度的节点访问,优于vector的$O(n)$查找[^3] --- #### 四、自定义类型哈希(高级应用) 使用自定义类作为键的示例: ```cpp #include <unordered_map> struct Point { int x, y; bool operator==(const Point& other) const { return x == other.x && y == other.y; } }; namespace std { template<> struct hash<Point> { size_t operator()(const Point& p) const { return hash<int>()(p.x) ^ (hash<int>()(p.y) << 1); } }; } std::unordered_map<Point, std::string> pointMap; ``` 必须同时定义哈希函数和相等运算符[^3] --- #### 性能优化建议 1. **预分配空间**:通过`reserve()`预先分配足够桶数量 2. **选择高效哈希**:如字符串使用BKDR哈希[^3] 3. **开放定址法**:采用二次探测减少冲突概率[^4] ```cpp std::unordered_map<std::string, int> bigMap; bigMap.reserve(100000); // 预分配空间 ``` --- 相关问题
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值