15. 三数之和(中等)(LCR 007)

https://leetcode.cn/problems/3sum/
给你一个整数数组 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]]

示例 2:
输入:nums = [0,1,1]
输出:[]
解释:唯一可能的三元组和不为 0 。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        # 时间复杂度:O(n^2)
        # 空间复杂度:O(1)
        # 难度:☆☆☆
        # 数组有序,相向双指针
        # 和167题对照看,167题是两数之和等于target,本题可以看成nums[j] + nums[k] = -nums[i],也是一种两数之和等于target
        # 本题不是求索引,而是求数字,那么可以先排序,然后用相向双指针
        # 要求不包含重复三元组,像示例1一样,遍历了-1后组成[-1,0,1]符合结果,但是-1有2个,第2个-1必须忽略
        # 抽象成语句就是,当前值nums[i]和前一个值nums[i - 1]如果相同,忽略本次循环
        nums.sort()
        ret = []
        n = len(nums)
        for i in range(n - 2): # 因为是i < j < k,三个数,所以遍历时i最多遍历到倒数第3个数
            if i >= 1 and nums[i] == nums[i - 1]:
                continue
            # 升序数组,最小的三个数和都大于0了,后面就不用遍历了
            if nums[i] + nums[i + 1] + nums[i + 2] > 0:  
                break
            # nums[i]和数组中最大的2个数相加小于0,忽略本次循环,注意不能break,因为num[i]后面会变大,还会有机会等于0
            if nums[i] + nums[-2] + nums[-1] < 0:  
                continue
            # 以下代码就是167题的相向双指针思路
            left, right = i + 1, n - 1
            while left < right:
                sums = nums[i] + nums[left] + nums[right]
                if sums > 0:
                    right -= 1
                elif sums < 0:
                    left += 1
                else:
                    ret.append([nums[i], nums[left], nums[right]])
                    # 除了需要以nums[i]为标的的去重,以nums[left]和以nums[right]为标的的去重也要做
                    left += 1
                    while left < right and nums[left] == nums[left - 1]:
                        left += 1
                    right -= 1
                    while left < right and nums[right] == nums[right + 1]:
                        right -= 1
        return ret
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值