三数之和(排序、双指针解法)
转战C++了。
算法流程:
1.特判,对于数组长度n,如果数组为null或者数组长度小于3,返回{}。
2.对数组进行排序。
3.遍历排序后数组:
若nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于0,直接返回结果。
对于重复元素:跳过,避免出现重复解。
令左指针L=i+1,右指针R=n−1,当L<R时,执行循环:
- 当nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将L,R移到下一位置,寻找新的解。
- 若和大于0,说明nums[R]太大,R左移。
- 若和小于0,说明nums[L]太小,L右移。
摘自:LeetCode
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
vector<vector<int>> result;
int n = nums.size();
if (n<3)
return result;
//排序
sort(nums.begin(),nums.end());
for(int i=0;i<n;i++){
if (nums[i]>0)
return result;
if (i>0 && nums[i]==nums[i-1])
continue;
//定义左右指针
int lp = i+1;
int rp = n-1;
while (lp < rp)
{
if (nums[i]+nums[lp]+nums[rp]==0)
{
vector<int> vlist = {nums[i],nums[lp],nums[rp]};
result.push_back(vlist);
while (lp<rp && nums[lp+1]==nums[lp])
lp++;
while (lp<rp && nums[rp-1]==nums[rp])
rp--;
lp++;
rp--;
}else if (nums[i]+nums[lp]+nums[rp]>0)
rp--;
else
lp++;
}
}
return result;
}
};
int main(){
Solution s;
vector<int> vlist = {-1,0,1,0};
vector<vector<int>> vvint = s.threeSum(vlist);
for(int i=0;i<vvint.size();i++){
for(int j=0;j<vvint[i].size();j++){
cout << vvint[i][j] << " ";
}
cout << endl;
}
getchar();
return 0;
}
最接近的三数之和(排序、双指针解法)
很容易想到修改上面的代码即可。
#include <vector>
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
class Solution {
public:
int threeSumClosest(vector<int>& nums, int target) {
int n = nums.size();
if (n<3)
return 0;
//排序
sort(nums.begin(),nums.end());
int ans = nums[0]+nums[1]+nums[2];
for(int i=0;i<n;i++){
//定义左右指针
int lp = i+1;
int rp = n-1;
while (lp < rp)
{
int sum = nums[i]+nums[lp]+nums[rp];
if (abs(sum-target) < abs(ans-target)) //选择与目标差距更小的那一个
ans = sum;
if (sum == target)
return target;
else if (sum > target)
rp--;
else
lp++;
}
}
return ans;
}
};
int main(){
Solution s;
vector<int> vlist = {0,2,1,-3};
int target = 1;
cout << s.threeSumClosest(vlist,target) <<endl;
getchar();
return 0;
}