#454四数相加II M 不会,好难,直接看思路+自己实现 30min,hash一般有思路了实现都挺快
!这个和后面同ary内三数四数之和的区别是,是在4个vec内,不用去重
分成 a+b c+d O(n^4)->O(n^2)
int fourSumCount(vector& nums1, vector& nums2, vector& nums3, vector& nums4) {
unordered_map abmap;
int cnt=0;
for (auto &ele1:nums1){
for (auto &ele2:nums2){
abmap[ele1+ele2]+=1;
}
}
for(auto & ele3:nums3){
for (auto &ele4:nums4){
if(abmap.find(0-ele3-ele4)!=abmap.end()){
cnt+=abmap[0-ele3-ele4];
}
}
}
return cnt;
}
#383 赎金信 E 自己做很快
记得map中map[ ]--到0时要手动erase,不然后面find判断会出错
bool canConstruct(string ransomNote, string magazine) {
unordered_map mmap;
for(char &c:magazine){
mmap[c]++;
}
for(char &c:ransomNote){
if(mmap.find(c)!=mmap.end()){
mmap[c]--;
if(mmap[c]==0){
mmap.erase(c);
}
}
else{
return false;
}
}
return true;
}
但代码随想录用ary做hash更好!因为”本题情况下,使用map的空间消耗要比数组大一些的,因为map要维护红黑树或者哈希表,而且还要做哈希函数,是费时的!数据量大的话就能体现出来差别了。 所以数组更加简单直接有效!”可行的情况下hash用ary做是很好的
bool canConstruct(string ransomNote, string magazine) {
int record[26] = {0};
//add
if (ransomNote.size() > magazine.size()) {
return false;
}
for (int i = 0; i < magazine.length(); i++) {
// 通过recode数据记录 magazine里各个字符出现次数
record[magazine[i]-'a'] ++;
}
for (int j = 0; j < ransomNote.length(); j++) {
// 遍历ransomNote,在record里对应的字符个数做--操作
record[ransomNote[j]-'a']--;
// 如果小于零说明ransomNote里出现的字符,magazine没有
if(record[ransomNote[j]-'a'] < 0) {
return false;
}
}
return true;
}
#15 3sum == 0 M 难而经典
关键:i left right 三个指针,i正常遍历,left,right根据sum情况不断变化
去重!i是nums[i]==nums[i-1]之后就会产生一样的tuple,right和left是路上的下一个如果遇到一样的就跳过;但是i是要用前一个比,而不是下一个,因为是可以 (-1,-1,2)这样的
关于两个去重while的条件,我觉得left
vector> threeSum(vector& nums) {
sort(nums.begin(), nums.end());
vector> res;
int left,right;
for(int i=0;i0){return res;}
if(i>=1 && nums[i]==nums[i-1]){continue;}
left=i+1;
right=nums.size()-1;
while(left0){right--;}
else if(nums[i]+nums[left]+nums[right]<0){left++;}
else{//==0
res.push_back({nums[i],nums[left],nums[right]});
//while(left= 0 && nums[right] == nums[right - 1]) { right--; }
while(left + 1 < nums.size() && nums[left] == nums[left + 1]) { left++; }
right--;
left++;
}
}
}
return res;
}
#18 4sum == target M 难而经典,3sum基础上多考虑的东西:
k,i ,left,right 四个;target可能为正、负、0,剪枝(break/continue)条件只能用正的case
我看了思路自己实现错的地方:
1. i>k+1 那里开始写的不对,因为i=k+1,要在当前k循环中第二次看见某个数,必然i>k+1这个初始值
2.long那里老弄不对
long sum = (long)nums[k] + (long)nums[i] + (long)nums[left] + (long)nums[right]; 这是对的
long sum = (long) nums[k] + nums[i] + nums[left] + nums[right] 这也是对的
long sum = (long)(nums[k] + nums[i] + nums[left] + nums[right])但这是错的,因为后面那些int加起来已经溢出了
anyway有很大的数,很多的数相加一定要注意type只是int会不会溢出
vector> fourSum(vector& nums, int target) {
sort(nums.begin(),nums.end());
vector> res;
int left,right;
for (int k=0;k=target && nums[k]>0){break;}//>= > ???
if(k>=1 && nums[k]==nums[k-1]){continue;}
for (int i=k+1;i=target && nums[i]+nums[k]>0){break;}
if(i > k+1 && nums[i]==nums[i-1]){continue;} //在当前k循环中第一次看到这数
left=i+1;
right=nums.size()-1;
while(lefttarget){right--;}
else if(sum