理解
哈希表通过哈希函数计算出特定的位置,把待存储的值放在那。这样,只要我们知道哈希函数,就能快速知道元素的存储位置,时间复杂度为常数时间复杂度O(1)。
同时,不同元素通过哈希函数计算出来的哈希地址可能有冲突,因此,需要引入冲突解决方法:链地址、哈希函数再散列等。哈希函数一般选质数,但也不能避免冲突出现,例如,哈希函数为(a%11)时,待存元素2,13会有冲突。
哈希表实现可用的数据结构
- 数组
- set
- map
例题
1、两数之和
本题适用哈希表存储是因为:在遍历到a时,若该序列中(target-a)存在,则它的地址是(target-a)%hashkey,若在那个地址已经有值存储,说明这俩元素符合题意。
https://github.com/youngyangyang04/leetcode-master/blob/master/problems/0001.%E4%B8%A4%E6%95%B0%E4%B9%8B%E5%92%8C.md
2、四数之和Ⅱ
3、三数之和
个人理解
- 题目中说的重复三元组:
指的是两个
三元组组内元素一致。例如[-7,3,4]和[-7,3,4]这两个三元组,但是组内元素是可以重复的,例如[-2,1,1],[-2,-2,4]这种三元组只是组内元素重复,是满足题目要求的。也就是说重复是有两个维度上的重复:组间重复
和组内元素重复
- 去重
a的去重条件无论哈希法还是双指针法都是和前一个元素比较nums[i] == nums[i - 1]
。目的
就是防漏漏掉[-x,-x,2x]
这种三元组,现在写的逻辑都是固定a,找出包含它的所有三元组,所以下一次判断包含该元素的三元组时,需要去重。 - Carl哥代码理解
set的作用一开始没看明白:其实是自己默认了遍历过程中三元组的元素也是排序的,实际上set里存的相当于排序了的三元组中间的那个元素。set存的其实就是已经遍历了的数,nums[i+1]~nums[j-1]这一部分(注意去重)
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
sort(nums.begin(), nums.end());
// 找出a + b + c = 0
// a = nums[i], b = nums[j], c = -(a + b)
for (int i = 0; i < nums.size(); i++) {
// 排序之后如果第一个元素已经大于零,那么不可能凑成三元组
if (nums[i] > 0) {
break;
}
if (i > 0 && nums[i] == nums[i - 1]) { //三元组元素a去重
continue;
}
unordered_set<int> set;//存储三元组中中间数字
for (int j = i + 1; j < nums.size(); j++) {
if (j > i + 2
&& nums[j] == nums[j-1]
&& nums[j-1] == nums[j-2]) { // 三元组元素b去重,防止0,0,0去掉
continue;
}
int c = 0 - (nums[i] + nums[j]);
if (set.find(c) != set.end()) {//set,find()若执行失败,返回end()
result.push_back({nums[i], nums[j], c});
set.erase(c);// 三元组元素c去重
} else {
set.insert(nums[j]);
}
}
}
return result;
}
};