描述
给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != j、i != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请
你返回所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
示例 1:
输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]] 解释: nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。 nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。 nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。 不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。 注意,输出的顺序和三元组的顺序并不重要。 示例 2:
输入:nums = [0,1,1] 输出:[] 解释:唯一可能的三元组和不为 0 。 示例 3:
输入:nums = [0,0,0] 输出:[[0,0,0]] 解释:唯一可能的三元组和为 0 。
提示:
3 <= nums.length <= 3000 -105 <= nums[i] <= 105
分析
首先,我们需要可以使用暴力法分析,即从首到尾选一个,然后每一个又选一个,最后再选一个,此时需要n^3次方。 但是,我们可以知道,每一个都有重复的值,且都可能导致重复,所以我们需要进行排序。 排序后,我们可以从小到大选一个first,并用一个target当作first对应的负数。 此时,我们就只需要选取两个,由于我们已经排序了,我们可以使用双指针首尾收缩,逐个匹配值
代码
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
Arrays.sort(nums);
List<List<Integer>> res=new ArrayList<>();
int first=0,second=0,third=0;
for (;first<nums.length-2;++first){
if(first>0&&nums[first]==nums[first-1]){
continue;
}
int target=-nums[first];
third=nums.length-1;
for (second=first+1;second<nums.length-1;++second){
if(second > first + 1&&nums[second]==nums[second-1]){
continue;
}
while (second<third&&nums[second]+nums[third]>target){
third--;
}
if (second == third) {
break;
}
if(nums[second]+nums[third]==target){
List<Integer> list=new ArrayList<>();
list.add(nums[first]);
list.add(nums[second]);
list.add(nums[third]);
res.add(list);
}
}
}
return res;
}
}