题目
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4]
输出:[[-1,-1,2],[-1,0,1]]
题解
- 暴力遍历
用三个指针遍历,要求无重复数组,则先排序,然后遇到一样的跳过。时间复杂度为O(n^3),运行超时。代码如下
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
List<List<Integer>> res = new ArrayList<>();
if (n < 3||nums == null) return res;
Arrays.sort(nums);
for (int i = 0; i < n-2; i++){
if (i > 0&&nums[i] == nums[i-1]) continue;
for (int j = i + 1; j < n-1; j++){
int target = -(nums[i] + nums[j]);
if (j > i + 1&&nums[j] == nums[j - 1]) continue;
for (int k = j + 1; k < n; k++){
if (k > j + 1&&nums[k] == nums[k - 1]) continue;
if (nums[k] == target) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
res.add(list);
}
}
}
}
return res;
}
- 改进
固定一个元素后,用双指针同时遍历。用排序去重,三个元素,去两次重,当与上一个元素一样时,则跳过。代码如下:
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
List<List<Integer>> res = new ArrayList<>();
if (n < 3||nums == null) return res;
Arrays.sort(nums);
for (int i = 0; i < n - 2; i++){
if (i > 0&&nums[i] == nums[i-1]) continue;
int target = -nums[i];
int k = n-1;
for (int j = i + 1; j < n; j++){
if (j > i + 1&&nums[j] == nums[j - 1]) continue;
while (j < k&&nums[j] + nums[k] > target) {
k--;
}
if (j == k) break;
if (nums[j] + nums[k] ==target) {
List<Integer> list = new ArrayList<>();
list.add(nums[i]);
list.add(nums[j]);
list.add(nums[k]);
res.add(list);
}
}
}
return res;
}
类似的还有力扣18-四数之和