1.题目
2.思路
显然三层for循环的时间复杂度会超时,为了减少时间复杂度我们要去除重复解,逐个遍历数组元素,转成求两数之和,用双指针。
PS:按照题目意思不能包含重复的三元组,所以比如,如果有多个-1组成的(-1,0,1)也只能算一个。
核心步骤(排序数组后):
- 当nums[i]+nums[L]+nums[R]==0,执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 L,R移到下一位置,寻找新的解
- 若和大于 0,说明 nums[R]太大,R左移
- 若和小于 0,说明 nums[L]太小,L 右移
3.代码
class Solution {
public:
vector<vector<int>> threeSum(vector<int>& nums) {
int size = nums.size();
vector<vector<int>>ans;
if(size < 3){
return ans;//没有三个数
}
sort(nums.begin(), nums.end());//从小到大排序
for(int i = 0;i < size; i++){
if(nums[i] >0){
return ans;//最小的数字都大于0就没得玩了
}
//去重
if(i > 0 && nums[i] == nums[i - 1]){
continue;
}
int left = i + 1;
int right = nums.size() - 1;
while(left < right){
//三种情况
if(nums[left] + nums[right] + nums[i] > 0){
right--;
}else if(nums[left] + nums[right] + nums[i] < 0){
left++;
}else{
ans.push_back({nums[left], nums[right], nums[i]});
//判断左界和右界是否和下一位置重复,去重
while(right > left && nums[right] == nums[right - 1]){
right--;
}
while(right > left && nums[left] == nums[left + 1]){
left++;
}
left++;
right--;
}
}
}
return ans;
}
};