看到题目首先想到两数之和,两数之和的解法很普通,就是先对数进行排序,然后利用双指针,一个指向左边,一个指向右边。当两指针之和大于目标值时,移动右指针,当和小于目标值时,移动左指针。该题思路大致和其差不多相同。但开始的时候,大家最先想到的是利用三个for循环来遍历数组,这样虽然可以一样解出来,但所需的时间复杂度太高,所以需要改进算法。
具体思路是将其类比与两数之和,先固定一个“目标值”,然后利用双指针,分别从左和右遍历数组,判断其与“目标值”的大小关系,同时因为题目要求不能包含重复的三元组,所以在遍历的时候需要注意判断其值是否重复。
下面附上简洁一点的代码,用while循环看起来比用for循环简洁清晰。
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(),nums.end());
vector<vector<int>> ans;
if(n < 3)return {};
for(int i = 0;i < n;i++){
if(nums[i] > 0)return ans;
if(i > 0 && nums[i] == nums[i - 1])continue;//判断其值是否与重复
int left = i + 1; //左指针
int right = n - 1; //右指针
while(left < right){ //结束条件
//如果两指针相加大于“目标值”,右指针移动
if(nums[left] + nums[right] > -nums[i])right--;
//如果两指针相加小于“目标值”,左指针移动
else if(nums[left] + nums[right] < -nums[i])left++;
else{
ans.push_back({nums[i],nums[left],nums[right]});
left++;
right--;
while(left < right && nums[left] == nums[left - 1])left++;//判断重复
while(left < right && nums[right] == nums[right + 1])right--;//判断重复
}
}
}
return ans;
}
};