题目链接
题目:
分析:
- 解法一: 暴力解法, 将所有的三元组都算出来看是否为0, 题目要求去重操作, 所以我们可以使用set去重
- 解法二:
- 因为我们知道当计算两数之和时, 我们使用的方法是将数组排序,然后利用"双指针"
- 那么同理, 计算三个数之和:
- 1. 排序
- 2. 固定一个数a, 因为要找和为0的组, 所以当a为正数时, 此时a后面的数据都是>0的, 那么和一定是>0, 所以我们可以做一个小优化: 当a<= 0 时, 才继续判断
- 3. 在该数后面的区间中, 利用"双指针", 找到两数之和 = -a 即可
- 如何去重?
- 因为我们已经将数组排序, 那么相同的数据一定是挨着的, 不用重复计算, 所以当我们判断完一组数据后, 假设我们要left++ , 但这时, 我们还需循环判断此时的数据和前面是否相同, 如果相同, 则left继续++, right同理--
- 但是此时我们要思考一个问题: 不能越界 如果此时left到right之间的数都是相同的, 那么我们只能++到right, 同理right也只能--到left, 所以在循环时我们要加上left<right的条件
- 那么同理, 当a在++时, 也要做到跳过重复, 并且不能越界
- 如何保证返回所有的结果?
- 在找到一组数据后, 不能直接返回, 需要继续找下一组数据, 所以需要left++ right--
代码:
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
int i = 0;
List<List<Integer>> list = new ArrayList<>();
while (i < nums.length && nums[i] <= 0) {
int left = i + 1;
int right = nums.length - 1;
int target = -nums[i];
while (left < right) {
if (nums[left] + nums[right] < target) {
left++;
} else if (nums[left] + nums[right] > target) {
right--;
} else {
list.add(Arrays.asList(nums[i], nums[left], nums[right]));
left++;
right--;
while (nums[left] == nums[left - 1] && left < right) {
left++;
}
while (nums[right] == nums[right + 1] && left < right) {
right--;
}
}
}
i++;
while (i < nums.length && nums[i] == nums[i - 1]) {
i++;
}
}
return list;
}
}