Leetcode 15. 三数之和

189 阅读2分钟

Leetcode 15. 三数之和

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第6天,点击查看活动详情

❤️‍欢迎订阅java厂长《LeetCode每日一题》 ❤️‍

1、题目📑

给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 abc ,使得 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

2、思路🧠

方法一:暴力

  • 暴力的时间复杂度为 O(N3) ,但是可通过双指针动态消除掉无效解。

方法二:排序 ➕ 双指针

本题的难点在于如何消除重复解,以提高效率。

  1. 特判:如果数组的为 null 或者 长度 < 3,直接返回空集合。
  2. 初始化:
    • 对数组先进行排序,排序后出现固定位置的数字大于0,则后面的数字不用进行考虑,直接结束
    • 确定固定指针 k ,定义双指针 ij
    • 求和结果sum,sum = nums[i] + nums[j] + nums[k];
  3. 循环遍历:
    • num[k] > 0 :因为已经排序,所以后面不可能出现三个数相加和等于 0 的情况,直接结束。
    • 重复元素:出现相同的元素,跳过
    • L<R 时,执行循环:
      • 若和大于 0 sum > 0,则说明 nums[j] 太大,j 左移
      • 若和小于 0 sum < 0,则说明 nums[i] 太小,i 右移
      • 若和等于 0 sum == 0,执行循环,去判断左和右数字是否与下一位置重复,目的是去除重复解。并同时将 ij 移到下一位置,寻找新的解
  4. 返回结果 res

废话少说~~~~~上代码!

3、代码👨‍💻

第一次commit AC

public static List<List<Integer>> threeSum(int[] nums) {
    List<List<Integer>> res = new ArrayList<>();
    Arrays.sort(nums);
    for (int k = 0; k < nums.length - 2; k++) { //固定其中一个指针
        if(nums[k] > 0) break; //排序后,第K个位置的数字大于0,则K位置之后的数字都大于0
        if (k > 0 && nums[k] == nums[k  - 1]) continue; //当前k位置的元素与前一个位置元素相同则不用在进行查找
        int i = k + 1, j = nums.length - 1;
        while(i < j) {
            int sum = nums[i] + nums[j] + nums[k];
            if (sum < 0) {
                i+=1;
            }else if(sum > 0) {
                j-=1;
            }else {
                res.add(Arrays.asList(nums[k], nums[i], nums[j]));
                while(i < j && nums[i] == nums[i + 1]) i+=1; //当前i位置的元素与前一个位置元素相同则不用在进行查找
                while(i < j && nums[j] == nums[j - 1]) j-=1; //当前j位置的元素与前一个位置元素相同则不用在进行查找
                i+=1;
                j-=1;
            }
        }
    }
    return res;
}

时间复杂度:O(N2),数组排序 O(NlogN),遍历数组 O(N),双指针遍历 O(N),总体 O(NlogN) ➕ O(N) ✖ O(N) 💨 O(N2)

空间复杂度:O(1)

image-20220531114504855

4、总结

该题目的对重复解的去重进行考察和练习,同时对于数组要有排序的敏感度,对双指针的解法也要非常的熟悉,并且能够想到具体问题具体解决。

❤️‍来自专栏《LeetCode基础算法题》欢迎订阅❤️‍

厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。

对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!

原题链接:15. 三数之和 - 力扣(LeetCode)