LeetCoder____Two Sum(1)
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
题意:
输入一个数组,和一个目标值,从数组找出两个数使得其和为目标值
LeetCoder____3 Sum(15)
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
题意:
输入一个数组,和一个目标值,从数组找出三个数使得其和为目标值,找出所有满足的组合,但是不能重复。
LeetCoder____4 Sum(18)
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
题意:
输入一个数组,和一个目标值,从数组找出四个数使得其和为目标值,找出所有满足的组合,但是不能重复。
分析:
这类题目,要找到目标组合不难,如果要找出所有的目标组合并且要排除所有重复组合这就是一个难点。
假如不用排除重复组合,则有几种方法可以来处理:
1.排序后,用二分查找。
2.用map来存储变量,查找复杂度logn。
以上方式有个最大的弊病,无法处理重复组合,只能生成之后再去排重,排重的时间复杂度很高。
所以如果要排除重复组合,则可以利用一下方式来处理:
1.二指针。
这样在生成的时候就可以排重了!
用2 Sum来举例:
先将数组排序,然后使两个"指针",指向首尾。如果两个指针对应值加起来小于目标值就向右移动左“指针”,如果加起来大于目标值就向左移动右“指针”。直到两个指针对应值相加为目标值。
代码:
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
sort(nums.begin(),nums.end());
int l = 0,r = nums.size() - 1;
while(l < r){
if(nums[l]+nums[r] == target)return {l,r};
if(nums[l]+nums[r] < target)l++;
else r--;
}
return null;
}
};
注意:本代码不是leetcoder1的代码。
2.由上面的two sum推导到3 Sum,并且找出所有组合并且要去重。
如何去重呢? 只要保证左右指针不处理同样的元素就行了。这样在处理的时候就已经排除掉重复的组合 了。
如何由Two sum 问题推导到 3 sum。只需要for循环枚举组合的第一个数,然后从第一个数位置之后又转化为Two sum问题了。只是区间变了。
代码:
class Solution {
public:
vector<vector<int>> threeSum( vector<int> nums) {
if(nums.size() < 3) return vector<vector<int>>();
sort(nums.begin(),nums.end());
vector<vector<int>> ans;
for(int i = 0 ; i < nums.size() ; i ++){
if(i != 0 && nums[i] == nums[i-1])continue;
int l,r;l = i + 1,r = nums.size() - 1;
while(l<r){
if(r != nums.size() - 1 && nums[r] == nums[r+1]){
r --; continue;
}
if(l != i + 1 && nums[l] == nums[l-1]){
l++; continue;
}
if(nums[l] + nums[r] == -nums[i]){
ans.push_back({nums[i],nums[l],nums[r]});
l ++;
}else if(nums[l] + nums[r] > -nums[i]){
r --;
}else if(nums[l] + nums[r] < -nums[i]){
l ++;
}
}
}
return ans;
}
};
4.4Sum 和前面的一样,枚举组合的前面两个数,然后对于最后两个数依然使用双指针。
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
vector<vector<int>> ans;
sort(nums.begin(),nums.end());
int n = nums.size();
for(int i = 0 ; i < n-3 ; ++ i){
if(i != 0 && nums[i] == nums[i-1])continue;
if(nums[i] + nums[n-1] + nums[n-2] + nums[n-3] < target)continue;
if(nums[i] + nums[i+1] + nums[i+2] + nums[i+3] > target)break;
for(int j = i+1 ; j < n-2 ; ++ j){
if(j != i+1 && nums[j] == nums[j-1])continue;
if(nums[i] + nums[j] + nums[n-1] + nums[n-2] < target)continue;
if(nums[i] + nums[j+1] + nums[j+2] + nums[j] > target)break;
int l = j+1,r = n - 1;
while(l < r){
if(l != j+1 && nums[l] == nums[l-1]){
l ++;continue;
}
if(r != n-1 && nums[r] == nums[r+1]){
r --;continue;
}
if(nums[i] + nums[j] + nums[l] + nums[r] == target){
ans.push_back({nums[i],nums[j],nums[l],nums[r]});
l++;
}else if(nums[i] + nums[j] + nums[l] + nums[r] > target){
r--;
}else{
l++;
}
}
}
}
return ans;
}
};