LeetCode 三数之和

简介: 本题目主要是更加深化的考察双指针的运用,这里是需要在一个数组中,找到三个数的和为0 的所有三元组,其实可以看作是两个双指针然后最终合并起来,得到一个结果等于期望的值。举一反三如果a + b + c = n , n 是一个传入的变量,解题思路也是一样的。 对于结果集合不能重复的话,我们最常用的方式就是直接通过排序的方式来做,就可以在拿这个数据的时候,直接判断拿过了没有,拿过这个数据就跳过。下面我们就一起来看看具体的题目和解题分析吧

三数之和


题目


给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。


注意:答案中不可以包含重复的三元组。


示例 1:


输入:nums = [-1,0,1,2,-1,-4] 输出:[[-1,-1,2],[-1,0,1]]


示例 2:


输入:nums = [] 输出:[]


示例 3:


输入:nums = [0] 输出:[]


提示:


0 <= nums.length <= 3000 -105 <= nums[i] <= 105


题目分析


1. 暴力解题


时间复杂度:O(N * N *N)

空间复杂度:O(1)


直接通过三重循环来计算。


2. 优化思路


时间复杂度:O(N * N *N)

空间复杂度:O(logN)


解题关键:排序 + 双指针。


题目中要求是不能重复的, 我们可以将输入的整个数组先排序来防止重复。


选择双指针的思路是,我们三个数的和其实可以先取出一个数,然后就看作两个数的和来处理,这样就可以灵活的运用双指针的思路了。


双指针过程中的指针移动。a , b,  c 下标的移动过程中。


  • a 下标需要遍历数组,得到 b + c 的和等于 -1 * a,需要通过前一个来判断是否是重复,如果已经存在就跳过。


  • b, c 双指针的移动过程,首先 b 指针初始化,为 a 下标 + 1; 并且通过前一个数来判断数据是否存在重复,如果已经存在就跳过。


  • c 指针的初始指针位置为 nums.length -1 。如果 a + b > -a 那么就需要把 c 指针左移,否者右移 b 指针,因为已经排序了的。


  • 如果 a + b == -a , 表示找到真确的结果,存储到返回的结果集中。


  • 如果 c 指针 == b 指针说明已经找了一圈了,就退出本次的循环,然后在回去移动 a 指针。


解题代码


public class NumThreeSumTest {
    public static void main(String[] args) {
        NumThreeSumTest numThreeSumTest = new NumThreeSumTest();
        List<List<Integer>> lists = numThreeSumTest.threeSum(new int[]{-1,0,1,2,-1,-4});
        System.out.println(lists);
    }
    public List<List<Integer>> threeSum(int[] nums) {
        // 数组长度
        int len = nums.length;
        // 排序
        Arrays.sort(nums);
        List<List<Integer>> result = new ArrayList<>();
        for (int first = 0; first < len; first++) {
            // 跳过相同的值
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            int third = len - 1;
            int target = -nums[first];
            for (int second = first + 1; second < len; second++) {
                // 跳过相同的值
                if (second > first + 1 && nums[second] == nums[second - 1]) {
                    continue;
                }
                // 保证 b 的指针在 c 的左边
                while (second < third && nums[second] + nums[third] > target) {
                    --third;
                }
                // 如果指针重合,随后 b 继续增加
                // 如果没有满足 a + b + c = 0 , 并且 b < c 了, 退出循环
                if (second == third) {
                    break;
                }
                // 找到合适的解,放入结果集合
                if (nums[second] + nums[third] == target) {
                    result.add(Arrays.asList(nums[first], nums[second], nums[third]));
                }
            }
        }
        return result;
    }
}


参考资料


leetcode-cn.com/problems/3s…


相关文章
|
3月前
|
Java C++ Python
leetcode-15:三数之和
leetcode-15:三数之和
20 0
|
3月前
|
Java 测试技术 C++
leetcode-18:四数之和
leetcode-18:四数之和
23 0
|
10月前
|
存储 测试技术 C++
力扣1-两数之和&力扣15-三数之和
力扣1-两数之和&力扣15-三数之和
50 0
|
10月前
|
算法 安全 Swift
LeetCode - #18 四数之和
不积跬步,无以至千里;不积小流,无以成江海,Swift社区 伴你前行。如果大家有建议和意见欢迎在文末留言,我们会尽力满足大家的需求。
|
10月前
|
算法 测试技术
leetcode:15.三数之和
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
58 0
|
10月前
|
存储
每日一题——三数之和(双指针)
每日一题——三数之和(双指针)
|
10月前
每日一题——四数之和(双指针解法)
每日一题——四数之和(双指针解法)
|
10月前
leetcode:18.四数之和
这题和前面的一道三数之和类似,解题的思路都一样,这里直接选取两个基准就可以了,然后循环出所有的组合进行判断,如果正好相等那么就加入Set集合中。
40 0
|
Java C++ Python
【LeetCode】 15. 三数之和
第15题. 三数之和
56 0
【LeetCode】 15.  三数之和
LeetCode 15 三数之和
LeetCode 15 三数之和
44 0