力扣:15. 三数之和(Python3)

题目:

给你一个整数数组 nums ,判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i != ji != k 且 j != k ,同时还满足 nums[i] + nums[j] + nums[k] == 0 。请

你返回所有和为 0 且不重复的三元组。

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

来源:力扣(LeetCode)
链接:力扣

示例:

示例 1:

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

nums[0] + nums[1] + nums[2] = (-1) + 0 + 1 = 0 。
nums[1] + nums[2] + nums[4] = 0 + 1 + (-1) = 0 。
nums[0] + nums[3] + nums[4] = (-1) + 2 + (-1) = 0 。
不同的三元组是 [-1,0,1] 和 [-1,-1,2] 。
注意,输出的顺序和三元组的顺序并不重要。


示例 2:

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

解释:唯一可能的三元组和不为 0 。


示例 3:

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

解释:唯一可能的三元组和为 0 。

解法:

首先将列表排序,排序后分成3个列表(negative,zero,positive),分别存放负数、0、正数。接着去除不可能用到的数,如果某数的绝对值大于min(最小2个负数之和的绝对值,最大2个正数之和),那么说明此数太大了或太小了,没有两数之和能等于该数。然后进入算法。

如果3数之和为0,只有4种可能,分别是0+0+0,负数+0+正数(正数=|负数|),负数1+负数2+正数(正数=|负数1+负数2|),正数1+正数2+负数(|负数|=正数1+正数2),所以分为这4种情况分别讨论。

1.0+0+0:如果zero中存在3个及以上个0,那就把[0,0,0]加入结果中。

2.负数+0+正数:如果zero中存在0,那么就需要考虑这种情况,判断negative和positive中有没有绝对值相同的数。

3.负数+负数+正数:这种情况相当于-(负数1+负数2)=正数,所以遍历positive(外层循环),取到的每个值设为y,用双指针思想遍历negative(内层循环),设x1=0,x2=len(negative-1),x1指向negative的头,x2指向negative的尾,如果-(negative[x1]+negative[x2])=y,那就添加到结果,x1+=1,在添加到结果的时候注意判断结果中是否已存在,不要重复添加。如果<y,x2-=1,说明此时负数之和还不够小,移动x2可以使负数之和更小。如果>y,x1+=1,说明此时负数之和太小,移动x1可以使负数之和变大。循环的终止条件是x1=x2,每次循环结束,x1、x2都要重置。

4.正数+正数+负数:和3同理。

知识点:

1.关于负数:可以直接在代表数值的变量前加“-”,相当于*(-1)。

2.list.append(element)和list.extend(sequence):都是向列表中添加元素,但是extend的参数必须是可迭代对象,同时extend和+=等价。append和extend的区别是当参数是可迭代对象时,append是作为整体加入,extend是取可迭代对象中每个元素依次加入。比如list=[1],list.append([2,3])输出是[1,[2,3]],listexpend([2,3])输出是[1,2,3]。

代码:

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        zero = [num for num in nums if num == 0]
        negative = [num for num in nums if num < 0]
        positive = [num for num in nums if num > 0]
        if len(positive) > 1 and len(negative) > 1:
            negative = [num for num in negative if num >= -(t6 := min(-(negative[0] + negative[1]), positive[-1] + positive[-2]))]
            positive = [num for num in positive if num <= t6]
        result = []
        if len(zero) >= 3:
            result.append([0, 0, 0])
        if zero:
            for num in negative:
                if -num in positive and (t := [0, num, -num]) not in result:
                    result.append(t)
        if len(negative) > 1 and len(positive) > 0:
            x1 = 0
            x2 = len(negative) - 1
            for y in positive:
                while x1 != x2:
                    if (t2 := -(negative[x1] + negative[x2])) == y and (t1 := [negative[x1], negative[x2], y]) not in result:
                        result.append(t1)
                        x1 += 1
                    elif t2 < y:
                        x2 -= 1
                    else:
                        x1 += 1
                x1 = 0
                x2 = len(negative) - 1
        if len(positive) > 1 and len(negative) > 0:
            x1 = 0
            x2 = len(positive) - 1
            for y in negative:
                while x1 != x2:
                    if (t4 := positive[x1] + positive[x2]) == -y and (t3 := [positive[x1], positive[x2], y]) not in result:
                            result.append(t3)
                            x1 += 1
                    elif t4 < -y:
                        x1 += 1
                    else:
                        x2 -= 1
                x1 = 0
                x2 = len(positive) - 1
        return result

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值