目标
● 454.四数相加II
● 383. 赎金信
● 15. 三数之和
● 18. 四数之和
● 总结
454.四数相加
思路:早上起来没有思路一脸懵,只想到了暴力破解
看了题解,搜嘎。转变成两数相加,前两个数一组,后两个数一组
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int, int> hash;
int len = nums1.size();
int count = 0;
for(int i : nums1)
for(int j : nums2)
++hash[0 - i - j];
for(int i : nums3)
for(int j : nums4)
if(hash.find(i + j) != hash.end())
count += hash[i + j];
return count;
}
如果本题想难度升级:就是给出一个数组(而不是四个数组),在这里找出四个元素相加等于0,答案中不可以包含重复的四元组
思考:
383.赎金信
思路:ran里的所有字符都能在mag里找到。用unordered_map记录mag中字符及个数,遍历ran,从中寻找找到-1,找不到或小于0返回;
bool canConstruct(string ransomNote, string magazine) {
unordered_map<char, int> hash;
for(char c : magazine) {
++hash[c];
}
for(char c : ransomNote) {
if(hash[c] > 0){
--hash[c];
} else {
return false;
}
}
return true;
}
其实在本题的情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!(代码随想录)
bool canConstruct(string ransomNote, string magazine) {
int hash[26] = {0};
for(char c : magazine) {
hash[c-'a']++;
}
for(char c : ransomNote) {
if(hash[c-'a'] > 0){
--hash[c-'a'];
} else {
return false;
}
}
return true;
}
15.三数之和
思路:是的,又是做过但忘记的,怎么办,学而不思则罔,可我也思了呀。。。
应该还是hash保存nums[i] + nums[j] 的负数,然后去nums[k]中查询。但是下标要不相等,那就手动过滤
vector<vector<int>> threeSum(vector<int>& nums) {
// vector<vector<int>> res;
// int len = nums.size();
// sort(nums.begin(), nums.end());
// if(nums[0] > 0 || nums[len-1] < 0)
// return res;
// for(int i = 0; i < len; i++) {
// if (nums[i] > 0) break;
// if(i > 0 && nums[i] == nums[i - 1])
// continue;
// unordered_set<int> hash;
// for(int j = i + 1; j < len; j++) {
// if(j > i + 2 && nums[j-1] == nums[j] && nums[j-2] == nums[j])
// continue;
// int sum = 0 - nums[i] - nums[j];
// if(hash.find(sum) != hash.end()) {
// res.push_back({nums[i], nums[j], sum});
// hash.erase(sum);
// } else {
// hash.insert(nums[j]);
// }
// }
// }
// return res;
vector<vector<int>> res;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
if (nums[i] > 0) {
return res;
}
// 正确去重a方法
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while(right > left) {
if(nums[left] + nums[i] + nums[right] < 0) {
++left;
} else if (nums[left] + nums[i] + nums[right] > 0) {
--right;
} else {
res.push_back({nums[i], nums[left], nums[right]});
// 去重逻辑应该放在找到一个三元组之后,对b 和 c去重
while (right > left && nums[right] == nums[right - 1]) right--;
while (right > left && nums[left] == nums[left + 1]) left++;
// 找到答案时,双指针同时收缩
right--;
left++;
}
}
}
return res;
}
这里还是不太明白哈希法的去重逻辑
…把对应行注释后能清楚处理的什么场景,但是想不到为什么这么做