454 是找四个数相加等于零的情况,我瞎了
a+b+c+d=0 先算a+b key是a+b、value是a+b出现的次数,然后找-(c+d)就OK了
本题解题步骤:
-
首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。
-
遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。
-
定义int变量count,用来统计a+b+c+d = 0 出现的次数。
-
在遍历大C和大D数组,找到如果 0-(c+d) 在map中出现过的话,就用count把map中key对应的value也就是出现次数统计出来。
-
最后返回统计值 count 就可以了
class Solution {
public:
int fourSumCount(vector<int>& nums1, vector<int>& nums2, vector<int>& nums3, vector<int>& nums4) {
unordered_map<int,int>map1;
for(auto&a:nums1){
for(auto &b:nums2){
map1[a+b]++;
}
}
int count=0;
for(auto&c:nums3){
for(auto &d:nums4){
if(map1.find(-(c+d))!=map1.end())
count+=map1[-(c+d)];
}
}
return count;
}
};
一个函数秒杀 2Sum 3Sum 4Sum 问题 ---------lubuladong
三数之和其实就是两数之和的进化版
15三数之和
思路排序+双指针
首先1.处理size小于3
class Solution {
vector<vector<int>>TwoSum(vector<int>&nums,int start,int target){
vector<vector<int>>vec;
int len=nums.size();
int left=start,right=len-1;
while(left<right){
int sum=nums[left]+nums[right];
if(sum==target){
vec.push_back({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)
while(left<right&&nums[right]==nums[--right]);
else
while(left<right&&nums[left]==nums[++left]);
}
return vec;
}
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>vec;
if(nums.size()<3)return vec;
sort(nums.begin(),nums.end());
int n=nums.size();
for(int i=0;i<n-2;i++){
if(nums[i]>0)return vec;
if(i>0&&nums[i]==nums[i-1])continue;
int target=0-nums[i];
vector<vector<int>>tupless=TwoSum(nums,i+1,target);
if(!tupless.empty()){
for(auto &tmp:tupless){
tmp.push_back(nums[i]);
vec.push_back(tmp);
}
}
}
return vec;
}
};
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>>vec;
if(nums.size()<3)return vec;
sort(nums.begin(),nums.end());
int n=nums.size();
for(int i=0;i<n-2;i++){
if(nums[i]>0)return vec;
if(i>0&&nums[i]==nums[i-1])continue;
int left=i+1,right=n-1;
while(left<right){
int sum=nums[i]+nums[left]+nums[right];
if(sum==0){
vec.push_back({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(sum>0)
while(left<right&&nums[right]==nums[--right]);
else
while(left<right&&nums[left]==nums[++left]);
}
}
return vec;
}
};
时间复杂度:
因此枚举的总时间复杂度为 O(N^2)O(N^2)。由于排序的时间复杂度为 O(N log N)O(NlogN),在渐进意义下小于前者,因此算法的总时间复杂度为 O(N^2)O(N^2)。
作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/3sum/solution/san-shu-zhi-he-by-leetcode-solution/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
空间复杂度主要是排序nlogn,也可以看作O(n)
18 四数之和
这里由于不是零了,所以也就不存在当一个数大于target就返回的那种
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>>vec;
if(nums.size()<4)return vec;
sort(nums.begin(),nums.end());
int n=nums.size();
for(int i=0;i<n-3;i++){
// if(nums[i]>target)return vec;
if(i>0&&nums[i]==nums[i-1])continue;
for(int j=i+1;j<n-2;j++){
// int tmp=target-nums[i];
// if(nums[j]>tmp)break;
if(j>i+1&&nums[j]==nums[j-1])continue;
int left=j+1,right=n-1;
while(left<right){
if(nums[i]+nums[j]==target-nums[left]-nums[right]){
vec.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--;
right--;left++;
}else if(nums[i]+nums[j]>target-nums[left]-nums[right])
while(left<right&&nums[right]==nums[--right]);
else
while(left<right&&nums[left]==nums[++left]);
}
}
}
return vec;
}
};