美文网首页
15. 三数之和

15. 三数之和

作者: 一角钱技术 | 来源:发表于2020-08-22 21:55 被阅读0次

    15. 三数之和

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

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

    示例:
    给定数组 nums = [-1, 0, 1, 2, -1, -4],
    满足要求的三元组集合为:
    [
      [-1, 0, 1],
      [-1, -1, 2]
    ]
    

    算法思路:排序 + 双指针

    1. 特判,对于数组长度 len,如果数组为 null 或者数组长度小于 3,返回 []。
    2. 对数组进行排序。
    3. 遍历排序后数组:
      • 若 nums[i]>0:因为已经排序好,所以后面不可能有三个数加和等于 0,直接返回结果。
      • 对于重复元素:跳过,避免出现重复解
      • 令左指针 b = a + 1,右指针 c = len - 1,当 b < c 时,执行循环:
        • 当 nums[a]+nums[b]+nums[c]==0 执行循环,判断左界和右界是否和下一位置重复,去除重复解。并同时将 b, c 移到下一位置,寻找新的解
        • 若和大于 0,说明 nums[c] 太大,c 左移,即 c--;
        • 若和小于 0,说明 nums[b] 太小,b 右移,即 b++;

    参考代码

    class Solution {
        public List<List<Integer>> threeSum(int[] nums) {
            List<List<Integer>> list = new ArrayList<>();
            if (nums == null || nums.length < 3) {
                return list;
            }
            // 排序
            Arrays.sort(nums);
            int a = 0, b = 0, c = 0, len = nums.length, res = 0;
            // a 固定外层循环
            for (a = 0; a < len - 2; a++) {
                // 第一个元素
                if (nums[a] > 0) {
                    break;
                }
                // 去重
                if (a > 0 && nums[a] == nums[a-1]) {
                    continue;
                }
               
                b = a + 1;
                c = len - 1;
                // 最小值比较
                int min = nums[a] + nums[b] + nums[b+1];
                if (min > 0) {
                    break;
                }
                // 最大值比较
                int max = nums[c] + nums[c-1] + nums[c-2];
                if (max < 0) {
                    break;
                }
                 // b、c 双指针夹逼
                while (b < c) {
                    int target = nums[a] + nums[b] + nums[c];
                    if (target == 0) {
                        list.add(Arrays.asList(nums[a], nums[b], nums[c]));
                        b++;
                        c--;
                        // 去重
                        while (b < c && nums[b] == nums[b-1]) {
                            b++;
                        }
                        while (b < c && nums[c] == nums[c + 1]) {
                            c--;
                        }
                    } else if (target > 0){
                        c--;
                    } else {
                        b++;
                    }
                }
            }
            return list;
        }
    }
    

    复杂度分析

    • 时间复杂度:O(n^2)。数组排序 O(NlogN),遍历数组 O(n),双指针遍历 O(n),总体 O(NlogN) + O(n) * O(n),即 O(n^2)
    • 空间复杂: O(1)

    以上谢谢大家,求赞求赞求赞!

    💗 大佬们随手关注下我的wx公众号【一角钱小助手】和 掘金专栏【一角钱】 更多题解干货等你来~~

    相关文章

      网友评论

          本文标题:15. 三数之和

          本文链接:https://www.haomeiwen.com/subject/ycpujktx.html