454.四数相加II
和昨天那个两数之和为target有点像。
一开始想的是创建四个map分别存数组,但是这样跟暴力算法也没区别。
class Solution {
public:int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {unordered_map<int,int> map;int res=0;for(int n1:nums1){for(int n2:nums2){int sum=n1+n2;auto a=map.find(sum);if(a==map.end()){map.insert({sum,1});}else{a->second++;}}}for(int n3:nums3){for(int n4:nums4){auto a=map.find(-n3-n4);if(a!=map.end()){res+=a->second;}}}return res;}
};
小tips:
- 设置
auto a=map.find(sum);
在后面要a->second++;
的时候可以避免重复计算,降低时间复杂度。 - 计算结果数量的时候
res+=a->second;
,不能只加一次。
383.赎金信
一开始想到的省事的办法是用unorderd_map,但是题解里面说用um要维护哈希表还有使用哈希函数,费时间,在数据量大的时候更耗时,所以还是使用数组。
class Solution {
public:bool canConstruct(string ransomNote, string magazine) {int m[26]={0};for(char c:magazine){m[c-'a']++;}for(char c:ransomNote){if(--m[c-'a']<0) return false;}return true;}
};
可以在代码最前面加上一个判断,减少无用操作,提升运行速度
if (ransomNote.size() > magazine.size()) {return false;}
15.三数之和
尝试使用哈希。
要去重的话一个通用思路是要排序,这样才能把一样的元素放在一起。
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>> res;for(int i=0;i<nums.size();i++){if(nums[i]>0) break;if(i>0&&nums[i]==nums[i-1]) continue; //去重unordered_set<int> set;for(int j=i+1;j<nums.size();j++){//去重b=c时的情况if (j>i+2 && nums[j]==nums[j-1] && nums[j-1]==nums[j-2]) continue;int target=0-nums[i]-nums[j];if(set.find(target)!=set.end()){res.push_back({nums[i],nums[j],target});set.erase(target);//去重}else{set.insert(nums[j]);}}}return res;}
};
这个去重b==c时候的条件比较难想,还有这个set.erase(target)
通过了但是程序执行时间很长。
双指针写法执行时间快了不少,而且内存消耗也更低。
class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>> res;for(int i=0;i<nums.size();i++){if(nums[i]>0) break;if(i>0&&nums[i]==nums[i-1]) continue;int left=i+1;int right=nums.size()-1;while(left<right){int sum=nums[i]+nums[left]+nums[right];if(sum==0){res.push_back({nums[i],nums[left],nums[right]});while(left<right&&nums[right]==nums[right-1]) right--;while(left<right&&nums[left]==nums[left+1]) left++;left++;right--;}else if(sum>0) right--;else left++;}}return res;}
};
18.四数之和
在一个数组内并且要求去重,和三数之和比较像,考虑用双指针,for循环写两层。
class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {sort(nums.begin(),nums.end());vector<vector<int>> res;for(int i=0;i<nums.size();i++){if(nums[i]>target&&nums[i]>=0) break;if(i>0&&nums[i]==nums[i-1]) continue;for(int j=i+1;j<nums.size();j++){if(nums[i]+nums[j]>target&&nums[i]+nums[j]>=0) break;if(j>i+1&&nums[j]==nums[j-1]) continue;int left=j+1;int right=nums.size()-1;while(left<right){long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];if(sum==target){res.push_back({nums[i],nums[j],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(sum<target) left++;else right--;}}}return res;}
};
- 注意内层循环
if(j>i+1&&nums[j]==nums[j-1]) continue;
要和三数之和用哈希法if (j>i+2 && nums[j]==nums[j-1] && nums[j-1]==nums[j-2]) continue;
区分。j只要管好自己不要重复就行了。 long sum=(long)nums[i]+nums[j]+nums[left]+nums[right];
提交时提示sum会溢出,所以用long