Leetcode之15. 3Sum (medium)

15. 3Sum (medium)

描述

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.

Note:

The solution set must not contain duplicate triplets.

Example:

Given array nums = [-1, 0, 1, 2, -1, -4],

A solution set is:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

分析

首先是最容易想到的暴力破解,通过三重遍历数组nums,依次确定nums[i]nums[j]nums[k]并计算三元素之和是否为0。这是最粗暴的解法,但是存在去重的问题,如[-1, 0, 1]和[0, 1, -1]这种情况。

其次,这个题目作为2Sum的进阶题目,很容易联想到将3Sum转化为求target值为0 - nums[i],并在数组剩余元素中找出两个元素之和为target的2Sum问题。但是同样存在去重问题。

关于去重,由于是一个List

最后,以上两种思路都存在去重问题,问题需要的是找出数组中三个元素之和为0的所有组合。去重过程很明显是和结果无关,但是却非常麻烦,因此要优化算法就要着眼于移除去重这个步骤。

在暴力破解的时候就该意识到边界问题。

在做第一层循环时可以这样写:for(int i = 0; i < nums.length - 2; i++)。即第一层循环的结束条件是nums.length - 2,并不需要到nums.length

同样第二层循环时:for(int j = i + 1; j < nums.length - 1; j++)。开始索引不需要从0开始,可以直接从i + 1开始,而结束为nums.length - 1

第三层:for(int k = j + 1; k < nums.length; k++)

可以看到在暴力破解的时候,我们已经有意识地通过边界条件过滤掉一些情况,进行了初步优化。注意到数组本身是无序的,所以在确定元素的时候难以界定当前遍历元素是否已经被选中过。如果数组是有序的,那么三重遍历的时候就可以有意识地跳过重复元素。到这里已经对暴力破解的解题思路进行了优化,但是三重遍历无疑是导致时间复杂度为O(N^3),这么高的时间复杂度肯定是要被抛弃的。那么该如何继续优化呢?

尝试优化思路二。首先使用排序解决去重问题。遍历排序后的数组,固定第一个元素为nums[i],接下来在索引位i + 1nums.length之间找出两个元素nums[j]nums[k],二者之和为0 - nums[i]。固然这可以做遍历两次达到目的,相信基本上2Sum都是这样完成的。但是针对一个有序数组,夹逼法可以将这个过程的时间复杂度降为O(N)。因此,使用夹逼法找出剩余两个元素。ps,别忘了同时对2Sum使用夹逼法进行优化。

代码

public List<List<Integer>> threeSum(int[] nums) {
    List<List<Integer>> result = new LinkedList<List<Integer>>();
    if (nums == null || nums.length < 3) {
        return result;
    }
    // 对数组排序
    Arrays.sort(nums);
    //固定第一个元素nums[i]
    for (int i = 0; i < nums.length - 2; i++) {
        //默认是从小到大的排序,所以当nums[i]大于0的时候,就可以结束
        if (nums[i] > 0) {
            break;
        }
        //nums[i - 1] != nums[i]执行了去重,注意这里在理解的时候要意识到此时操作的数组已经是有序数组
        if (i == 0 || nums[i - 1] != nums[i]) {
            //使用加逼法
            int j = i + 1;
            int k = nums.length - 1;
            while (j < k) {
                int sum = nums[i] + nums[j] + nums[k];
                if (sum == 0) {
                    result.add(Arrays.asList(nums[i], nums[j], nums[k]));
                }
                if (sum <= 0) {
                    while (j < k && nums[j] == nums[++j]);
                }
                if(sum >= 0){
                    while (j < k && nums[k] == nums[--k]);
                }
            }
        }
    }
    return result;
}

上面的代码是优化之后的代码,对于理解加逼的过程有点不便,下面是加逼的原始写法:

while (j < k) {
    int target = 0 - nums[i];
    if(target == (nums[j] + nums[k])){
        result.add(Arrays.asList(nums[i], nums[j], nums[k]));
        j++;
        while(nums[j] == nums[j - 1] && j < k){ //去重,注意这是一个有序数组
            j++;
        }
        k--;
        while(nums[k] == nums[k + 1] && j < k){ //去重,注意这是一个有序数组
            k--;
        }
    }else if(target < (nums[j] + nums[k])){
        k--;
        while(nums[k] == nums[k + 1] && j < k){
            k--;
        }
    }else if(target > (nums[j] + nums[k])){
        j++;
        while(nums[j] == nums[j - 1] && j < k){
            j++;
        }
    }
}

原文地址:https://www.cnblogs.com/wxiaoqi/p/9736143.html

时间: 2024-12-15 09:06:40

Leetcode之15. 3Sum (medium)的相关文章

【leetcode】15. 3Sum

题目描述: Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. 解题分析: 这道题注意一下几点即可: 1,先固定前两个数的位置,移动第三个数,这样的查找方式不会有数字组合的遗漏: 2,要考虑到数组元素有重复的情况下的处理. 3,若先为数组排

15. 3Sum - Medium

Given an array nums of n integers, are there elements a, b, c in nums such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero. Note: The solution set must not contain duplicate triplets. Example: Given array nums =

[LeetCode][Python]15:3Sum

# -*- coding: utf8 -*-'''__author__ = '[email protected]' 15: 3Sumhttps://oj.leetcode.com/problems/3sum/ Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0?Find all unique triplets in the array which gives the sum

[LeetCode] 015. 3Sum (Medium) (C++/Java/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 015.3Sum (Medium) 链接: 题目:https://oj.leetcode.com/problems/3sum/ 代码(github):https://github.com/illuz/leetcode 题意: 在给定数列中找出三个数,使和为 0. 分析: 先排序,再左右夹逼,复杂度 O(n*n).

【LeetCode】16. 3Sum Closest

Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution. For example, given array S = {-1 2

leetcode -day 15 Distinct Subsequences

1.  Distinct Subsequences Given a string S and a string T, count the number of distinct subsequences of T in S. A subsequence of a string is a new string which is formed from the original string by deleting some (can be none) of the characters with

1. Two Sum&amp;&amp;15. 3Sum&amp;&amp;18. 4Sum

题目: 1. Two Sum Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice. Given nums = [2, 7, 1

[LeetCode] 039. Combination Sum (Medium) (C++)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 039. Combination Sum (Medium) 链接: 题目:https://leetcode.com/problems/combination-sum/ 代码(github):https://github.com/illuz/leetcode 题意: 给出一些正整数集合,以及一个目标数,从集合中选择一

[LeetCode] 031. Next Permutation (Medium) (C++/Python)

索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 031. Next Permutation (Medium) 链接: 题目:https://oj.leetcode.com/problems/next-permutation/ 代码(github):https://github.com/illuz/leetcode 题意: 求一个序列的下一个排列. 分析: 可以用