题目
给你一个包含 n 个整数的数组 nums
,判断 nums
中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例:
给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
解题思路
算法步骤:
1)首先对数组进行排序。
2)遍历排序后数组:
- 2.1)若 nums[first]>0,因为已经排序好,所以后面不可能有三个数之和等于 0,直接返回结果。
- 2.2)对于nums[first]的重复元素跳过,避免出现重复解。
- 2.3)令左指针 second=first+1,右指针 third=n-1,当 second<third 时,执行循环:
- 2.3.1)若和小于 0,说明 nums[second]太小,second 右移;
- 2.3.2)若和大于 0,说明 nums[third]太大,third 左移;
- 2.3.3)当和等于0,找到一个解,添加到结果中,同时将 second 右移, third 左移,判断新的左界及右界是否和上一位置重复,去除重复解。
复杂度分析:
时间复杂度:O(n^2),数组排序 O(nlogn),遍历数组 O(n),双指针遍历 O(n),总体 O(nlogn)+O(n)∗O(n) = O(n^2)
空间复杂度:O(logn),排序的空间复杂度为 O(logn)。
代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
int n = nums.length;
List<List<Integer>> res = new ArrayList<>();
// 先排序
Arrays.sort(nums);
for(int first=0; first<n; first++){
// 后面不可能有三个数加和等于 0,直接返回结果
if(nums[first]>0){
return res;
}
// 如果和上一个数相同,就跳过
if(first>0 && nums[first]==nums[first-1]){
continue;
}
int second = first+1;
int third = n-1;
while(second<third){
int sum = nums[first] + nums[second] + nums[third];
if(sum<0){
second++;
}else if(sum>0){
third--;
}else{
List<Integer> list = new ArrayList<>();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
res.add(list);
second++;
third--;
// 如果和上一个数相同,就跳过
while(second<third && nums[second]==nums[second-1]){
second++;
}
// 如果和上一个数相同,就跳过
while(second<third && nums[third]==nums[third+1]){
third--;
}
}
}
}
return res;
}
}