力扣 15题 : 三数之和

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

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/3sum
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法1 ,使用哈希表映射

参考:算法 - 哈希表 - 两数之和 与 四数之和


class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        List<List<Integer>> listList = new ArrayList<>();
        //Set是为了去除重复的list子集
        Set<List<Integer>> s = new HashSet<>();
        for (int i = 0; i < nums.length; i++) {
            int a = nums[i];
            Set<List<Integer>> sub = find2Pare(nums, i, 0 - a);
            s.addAll(sub);
        }
        listList.addAll(s);
        return listList;
    }

    /**
        把问题化解为两数之和
     */
    Set<List<Integer>> find2Pare(int[] nums, int start,  int target){
        Set<List<Integer>> lls = new HashSet<>();
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = start+1; i < nums.length; i++) {
            List<Integer> list = new ArrayList<>();
            if (map.get(target-nums[i]) != null) {
                list.add(nums[start]);
                list.add(nums[i]);
                list.add(target-nums[i]);
                Collections.sort(list);
                lls.add(list);
            }
            map.put(nums[i],i);
        }
        return lls;
    }

}

解法2 双指针法

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {

        // 先做排序
        Arrays.sort(nums);

        List<List<Integer>> lls = new ArrayList<>();
        for(int i  = 0 ; i < nums.length-2; i++) {
            // 如果当前数值大于0 ,因为是有序数组,后面的数值都是不可能和为0的,直接返回
            if(nums[i] > 0){
                return lls;
            }
            //对第一个数值去重
            if(i > 0 && nums[i] == nums[i-1]){
                continue;
            }
            int a = nums[i];
            int left = i+1;
            int right = nums.length-1;
            while(left < right){

                if(a + nums[left] + nums[right] == 0){
                    List<Integer> list = new ArrayList<>();
                    list.add(a);
                    list.add(nums[left]);
                    list.add(nums[right]);
                    lls.add(list);
                    
                    // 去重在找到第一个元素之后执行
                    // 对right指针元素去重
                    while(left < right && nums[right] == nums[right-1]){
                        right--;
                    }
                    // 对left指针元素去重
                    while(left < right && nums[left]== nums[left+1]){
                        left++;
                    }

                    // 找到答案后,双指针收缩
                    left++;
                    right--;
                }
                else if(a + nums[left] + nums[right] > 0){
                    right--;
                }else {
                    left++;
                }
            }
        }

        return lls;
    }

}

我有切糕
863 声望45 粉丝

Java架构师,技术经理