力扣刷题 - 哈希表
哈希表就是在关键字和存储位置之间建立对应关系。也就是:
flowchart LR A["关键字"] --> B["存储地址"] A@{ shape: rounded} B@{ shape: rounded} classDef default stroke-width:3px,font-size:16px,fill:transparent
在 C++ 中可以使用无序容器来实现:
// 头文件 |
可以看到 map [key] 既可以左赋值也可以右赋值,很灵活。
力扣 1
两数之和
在这里,对于一个固定值 target,我要找到数组中的对应元素以及他们的下标,那就先建立起数组元素 key 和他们下标 value 的映射,这样就构建出了一个哈希表 map,map 用来存放遍历过的元素,比如示例 1,当开始遍历元素 2 时,我想找到 7 是否遍历过,因为 9-2 = 7,但是发现没有,因此更新哈希表,将 key = 2 和 value = 0 放进 map 表中,然后开始遍历 7,在 map 中找有没有元素 2,如果找到了,返回 map 中 {2, 0} 集合,取 value = 0 和 value = 1,即构成了示例 1 的答案。
vector<int> twoSum(vector<int>& nums, int target) |
使用哈希表的时间复杂度为 $\small {O (N)}$,空间复杂度为 $\small {O (N)}$。比暴力解法 $\small {O (N^2)}$ 要快。
力扣 242
有效的字母异位词
这个题使用数组作为哈希表。由于 s 和 t 仅包含小写字母,可以统计两个字符串中 26 个小写字母出现的次数。如果 s 和 t 中 26 个字母出现的次数相等,说明 t 是 s 的字母异位词,如果不相等则不是。
bool isAnagram(string s, string t) |
力扣 349
两个数组的交集
这个题不适用数组作为哈希表进行解决,因为可能输入的数据量非常大,数组会增加存储开销。因此用 set 数据类型进行解决,set 和 map 一样,也是一类哈希表,不过只有一列数据。C++ 中可由下面定义:
//定义 |
这里先将 nums1 转换为 set 数据,然后查找 nums2 中的元素在 set 表中是否存在,如果存在就将结果保存下来,最后输出。这里用 set 还有一个好处就是会自动去重,所以无需处理结果中可能存在的重复元素。
vector<int> intersection(vector<int>& nums1, vector<int>& nums2) |
时间复杂度是 $\small {O (M + N)}$,$\small {N}$ 是遍历 nums2,$\small {M}$ 是最后 res 转换为 vector。空间复杂度是 $\small {O (N)}$。
力扣 454
四数相加 Ⅱ
这个题目如果使用暴力解法,复杂度是 $\small {O (N^4)}$。注意到题目要求 nums1 [i] + nums2 [j] + nums3 [k] + nums4 [l] == 0,也就是 nums1 [i] + nums2 [j] == - nums3 [k] - nums4 [l]。那么可以两两一组,先遍历计算 nums1 和 nums2 元素的和,并建立 map 表(这里用 map 表是因为可以利用 value 统计相同元素出现的个数),然后再遍历寻找 nums3 和 nums4 元素的和(取相反数)是否出现在 map 表中,如果出现将对应 value 值相加,最终就能够返回元组个数。
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) |
时间复杂度是 $\small {O\left (N^2 \right)}$,空间复杂度是 $\small {O\left (N^2 \right)}$。