题目
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解决方案:
先对数组做一下排序,排序完,是不是觉得思路有了,对的。我们只需要遍历前面的负数和0,也就是>0的我们统统不要了。
我们需要拿到第一个负数。拿到第一个负数后,我们只需要再拿到后面两个数,与之相加=0即可。后面两个数我们用两个指针来表示,j和k,一个是从左边往右边走,一个是从最右边往前走。有些思想就是想通的,之前的两数之和就是这种思路。先排好序,左边一个left指针,右边一个right指针,如果left+right > result,那么right往左移,如果left+right < result,那么说明相加得数不够,就需要left往右移。找到相加之和相等的就行。
不过在这里要注意一个问题,就是题目中提到的“答案中不可以包含重复的三元组”,所以我们需要把相同的数字过滤掉。只需要往下或者往前走一位,其他什么都不要做。
复杂度分析:
时间复杂度:
O(n^2)
空间复杂度:
o(n)
public static List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> ls = new ArrayList<>();
for (int i = 0; i < nums.length - 2; i++) {
if (i == 0 || (i > 0 && nums[i] != nums[i - 1])) { // 跳过可能重复的答案
int l = i + 1, r = nums.length - 1, sum = 0 - nums[i];
while (l < r) {
if (nums[l] + nums[r] == sum) {
ls.add(Arrays.asList(nums[i], nums[l], nums[r]));
while (l < r && nums[l] == nums[l + 1]) l++;
while (l < r && nums[r] == nums[r - 1]) r--;
l++;
r--;
} else if (nums[l] + nums[r] < sum) {
while (l < r && nums[l] == nums[l + 1]) l++; // 跳过重复值
l++;
} else {
while (l < r && nums[r] == nums[r - 1]) r--;
r--;
}
}
}
}
return ls;
}