解决这类问题首先需要了解双指针法的常见应用。双指针法是指在在遍历对象的过程中不适用单指针来进行遍历而是使用双指针来向相同或相反的方向进行遍历。双指针法中一个常见的问题就是:
给定有数组,来寻找两个满足条件的数。比如两个数的和等于给定值。
对于这种问题一种常见的思路是进行双指针遍历,具体思路是,对数组进行排序,然后设置两个指针,指针a指向数组的第一个元素,指针b指向数组的最后一个元素,在两指针相遇前,a只能向后移动,b只能向前移动。比较两指针所指向的数字和目标元素的值,如果较大则b向前移动,如果较小则a向后移动。
2sum,3sum,4sum都可以参考这种问题来进行解决。
leetcode的2sum,3sum,4sum都是比较经典的问题。
2 Sum
问题描述
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.
Example:
Given nums = [2, 7, 11, 15], target = 9, Because nums[0] + nums[1] = 2 + 7 = 9, return [0, 1].
思路
代码
class Solution {
public:
vector<int> twoSum(vector<int>& nums, int target) {
vector<int> ret;
int i,j;
unordered_map<int,int> maps;
for(i=0;i<nums.size();i++){
if(maps.find(target-nums[i])!=maps.end()){
ret.push_back(i);
ret.push_back(maps[target-nums[i]]);
break;
}
maps[nums[i]]=i;
}
return ret;
}
};
3 Sum
问题描述
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.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
思路
代码
class Solution {
public:
vector<vector<int> >ret;
vector<vector<int>> threeSum(vector<int>& nums) {
sort(nums.begin(),nums.end());
int i;
for(i=0;i<nums.size();i++){
if(i>0&&nums[i]==nums[i-1])
continue;
two_sum(nums,i+1,nums.size()-1,nums[i]);
}
return ret;
}
void two_sum(vector<int>& nums,int start,int end,int num){
int i=start;
int j=end;
while(i<j){
int sum=nums[i]+nums[j]+num;
if(sum>0)
j--;
else if(sum<0)
i++;
else if(sum==0){
vector<int> sub_ret;
sub_ret.push_back(num);
sub_ret.push_back(nums[i]);
sub_ret.push_back(nums[j]);
ret.push_back(sub_ret);
while(i<j&&nums[i]==nums[i+1])
i++;
while(i<j&&nums[j]==nums[j-1])
j--;
i++;
j--;
}
}
}
};
3 Sum Closest
问题描述
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
思路
代码
class Solution {
public:
int threeSumClosest(vector<int> &num, int target) {
int sum = 0;
sort(num.begin(), num.end());
int min_gap = INT_MAX;
for(auto start = num.begin(); start != prev(num.end(), 2); ++start){
auto mid = next(start);
auto last = prev(num.end(), 1);
while(mid < last){
int sumup = *start + *mid + *last;
int gap = abs(target -sumup);
if(gap < min_gap){
min_gap = gap;
sum = sumup;
}
if(sumup < target){
mid++;
}else{
last--;
}
}
}
return sum;
}
};
4 Sum
问题描述
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
思路
代码
class Solution {
public:
vector<vector<int>> fourSum(vector<int>& nums, int target) {
if(nums.size()<4)
return result;
sort(nums.begin(),nums.end());
int l=nums.size();
int i=0,j=0;
while(i<l-3){
j=i+1;
while(j<l-2){
int p=j+1;
int q=l-1;
while(p<q){
int sum=nums[i]+nums[j]+nums[p]+nums[q];
if(sum==target){
vector<int> temp;
temp.push_back(nums[i]);
temp.push_back(nums[j]);
temp.push_back(nums[p]);
temp.push_back(nums[q]);
result.push_back(temp);
while(nums[p]==nums[p+1])
p++;
while(nums[q]==nums[q-1])
q--;
p++;
q--;
}
else if(sum>target){
q--;
}
else if(sum<target){
p++;
}
}
while(nums[j]==nums[j+1])
j++;
j++;
}
while(nums[i]==nums[i+1])
i++;
i++;
}
return result;
}
private:
vector<vector<int>> result;
};