题目:
给你一个整数数组
nums
,判断是否存在三元组[nums[i], nums[j], nums[k]]
满足i != j
、i != 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