一 思路
看到本题的思路就是 排序+三重循环 进行求出所有存在的解
明显时间复杂度 为O(n^3) 最终超时;
思考过后能够知道 ,之前做过两数之和,实际上可以将第一次循环的值作为后面两数之和的target;是滴 这种可解
二 难点
注意循环操作 进行处理重复值的问题
三 结果
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
//找出存在的三元组 使a+b+c = 0
int n = nums.length;
Arrays.sort(nums);
List<List<Integer>> ans = new ArrayList<>();
//进行三个变量操作 i j k 转换为俩数之和
for (int first = 0; first < n; first++) {
//进行过滤掉相同的数据子集
// 需要和上一次枚举的数不相同
if (first > 0 && nums[first] == nums[first - 1]) {
continue;
}
// 固定第一个循环的值 然后第二三的循环就是两数之和
// c 对应的指针初始指向数组的最右端
int third = n - 1;
// -a = b + c
int target = -nums[first];
// 枚举 b
for (int second = first + 1; second < n; ++second) {
// 需要和上一次枚举的数不相同
if (second > first + 1 && nums[second] == nums[second - 1]) {
continue;
}
// 需要保证 b 的指针在 c 的指针的左侧
while (second < third && nums[second] + nums[third] > target) {
--third;
}
// 如果指针重合,随着 b 后续的增加
// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环
if (second == third) {
break;
}
if (nums[second] + nums[third] == target) {
List<Integer> list = new ArrayList<Integer>();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
ans.add(list);
}
}
}
return ans;
}
}
参考优秀的代码:
public List<List<Integer>> threeSum(int[] nums){
List<List<Integer>> lists = new ArrayList<>();
//排序
Arrays.sort(nums);
//双指针
int len = nums.length;
for(int i = 0;i < len;++i) {
//经过排序 如果第一层循环为 >0 就不会出现 =0的问题
if(nums[i] > 0) return lists;
if(i > 0 && nums[i] == nums[i-1]) continue;
//当前的第一层循环位置
int curr = nums[i];
int L = i+1, R = len-1;
while (L < R) {
int tmp = curr + nums[L] + nums[R];
if(tmp == 0) {
List<Integer> list = new ArrayList<>();
list.add(curr);
list.add(nums[L]);
list.add(nums[R]);
lists.add(list);
while(L < R && nums[L+1] == nums[L]) ++L;
while (L < R && nums[R-1] == nums[R]) --R;
++L;
--R;
} else if(tmp < 0) {
++L;
} else {
--R;
}
}
}
return lists;
}