454.四数相加II
链接:代码随想录
如果用哈希表,两个两个数组为一组,第一次存储任意两数之和的结果,存储在map中,然后后面两个边计算边查询结果即可。
class Solution { public: int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) { unordered_map<int,int>umap;//第一个key储存值,第二个储存index for(auto p: nums1) { for(auto q:nums2) { umap[p+q]++; } } int cnt=0; for(auto p3: nums3) { for(auto p4:nums4) { int temp=(-1)*(p3+p4); if(umap.find(temp)!=umap.end()) { cnt+=umap[temp]; } } } return cnt; } };
383. 赎金信
链接:代码随想录
基本思路:magzine 里的 映射到vector哈希表m[26]里去,然后遍历ransomNote,如果有<0,即false;否则m[ransomNote[i]-'a']--。不要求映射一对一的话,magzine 里的 映射可以有剩余。
class Solution { public: bool canConstruct(string ransomNote, string magazine) { vector<int>m(26,0); for(auto p:magazine) { m[p-'a']++; } for(auto q:ransomNote) { if(m[q-'a']<=0) { return false; } m[q-'a']--; } return true; } };
建议:本题虽然和 两数之和 很像,也能用哈希法,但用哈希法会很麻烦,双指针法才是正解,可以先看视频理解一下 双指针法的思路,文章中讲解的,没问题 哈希法很麻烦。
大概只想用双指针做。
基本思路:排序,会有重复的序列例如-2,-2,4-1,1,1这种,允许出现[-2,-2,4][-2,1,1],则第一个数是重复序列的第一个数,不是第一个数则continue.然后双指针遍历找出后面的两个数。
这道题做了很多遍还是错。建议看一遍,重写一遍。
if(nums[left]+nums[right]==temp)中进行添加数组、去重、和双指针同时收缩。
class Solution { /*[-2 -2 1 1 4] 包含 -2 -2 4 -2 1 1 */ public: vector<vector<int>> threeSum(vector<int>& nums) { vector<vector<int>> v; int n=nums.size(); sort(nums.begin(),nums.end()); for(int i=0;i<n;i++) { if(i>=1 && nums[i]==nums[i-1]) { continue; } int temp=0-nums[i]; int left=i+1; int right=n-1; while(left<right) { if(nums[left]+nums[right]==temp) { v.push_back({nums[i],nums[left],nums[right]}); while(left+1<right && nums[left]==nums[left+1]) { left++; } while(right-1>=0 && nums[right]==nums[right-1]) { right--; } //找到答案时,双指针需要同时收缩 right--; left++; } else if(nums[left]+nums[right]<temp) { left++; } else { right--; } } } return v; } };
18. 四数之和
链接:代码随想录
建议: 要比较一下,本题和 454.四数相加II 的区别,为什么 454.四数相加II 会简单很多,这个想明白了,对本题理解就深刻了。 本题 思路整体和 三数之和一样的,都是双指针,但写的时候 有很多小细节,需要注意,建议先看视频。
看了一遍,重写一遍。重写的过程中,有些小细节记得不清晰、
class Solution { public: /* 类三数之和,我哭死 */ vector<vector<int>> v; vector<vector<int>> fourSum(vector<int>& nums, int target) { int n=nums.size(); sort(nums.begin(),nums.end()); for(int i=0;i<n;i++) { long long temp=target-nums[i];//转换成三数之和!,但是应该也有去重问题,只计算第一个? if(i>0 && nums[i]==nums[i-1]) { continue; } //计算三数之和 ThreeSum(nums,temp,i); } return v; } void ThreeSum(vector<int>nums,long long target,int start_index) { //写三数之和 for(int i=start_index+1;i<nums.size();i++) { long long temp=target-nums[i]; if(i>start_index+1 && nums[i]==nums[i-1]) { continue; } int left=i+1; int right=nums.size()-1; while(left<right) { if(nums[left]+nums[right]==temp) { v.push_back({nums[start_index],nums[i],nums[left],nums[right]}); while(left<right && nums[left]==nums[left+1]) { left++; } while(left<right && nums[right]==nums[right-1]) { right--; } left++; right--; } else if(nums[left]+nums[right]>temp) { right--; } else { left++; } } } } };