力扣刷题-哈希表
哈希表就是在关键字和存储位置之间建立对应关系。也就是:
flowchart LR
A["关键字"] --> B["存储地址"]
A@{ shape: rounded}
B@{ shape: rounded}
classDef default stroke-width:3px,font-size:16px,fill:transparent
在C++中可以使用无序容器来实现:
1 | // 头文件 |
可以看到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的答案。
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的字母异位词,如果不相等则不是。
1 | bool isAnagram(string s, string t) |
力扣 349
两个数组的交集
这个题不适用数组作为哈希表进行解决,因为可能输入的数据量非常大,数组会增加存储开销。因此用 set 数据类型进行解决,set 和 map 一样,也是一类哈希表,不过只有一列数据。C++中可由下面定义:
1 | //定义 |
这里先将 nums1 转换为 set 数据,然后查找 nums2 中的元素在 set 表中是否存在,如果存在就将结果保存下来,最后输出。这里用 set 还有一个好处就是会自动去重,所以无需处理结果中可能存在的重复元素。
1 | 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值相加,最终就能够返回元组个数。
1 | 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)}$。





