三数之和(力扣15)

2024-05-20  
0条评论   142浏览

描述

给你一个整数数组 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;
    }
}