目录
题目
给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],
满足要求的三元组集合为:
[
[-1, 0, 1],
[-1, -1, 2]
]
思路
这道题是两数求和的扩展,如果不考虑重复情况的话这题其实很简单,这题的难点就是在于去除重复的情况,大致的思路如下:
最外层的遍历为遍历整个数组,对于当前遍历的每个数字,根据两数求和的思路去找到这样的满足情况的二元组(具体解法就是先排序数据,然后头尾指针,两边往里找直到找到满足情况的),然后将当前正在遍历的这个数字和二元组组成三元组作为其中的一个结果。
但是在遍历的时候,有可能会有相同的值的数字,这样就导致了有重复的三元组加入到结果中,所以我们在一开始就需要先对数组进行一个排序,举个例子排好序的数组为 -1 -1 0 1 2,
那么在处理第一个-1的时候,我们把所有两数相加为1的二元组找出来(这里注意是所有的这样的二元组,而不是找到一个就行),然后和-1组成三元组,那么在我们处理第二个-1的时候,就可以跳过去了。这是去除重复的其中一点,还有一点可能会发生重复的地方在于我刚刚说的,在寻找二元组的时候,有可能会寻找到重复的二元组,这样的话还是会造成重复,所以我们在寻找二元组的时候,要在满足相加等于第三个数的负数的时候,与前后的数字判断,相同就要跳过,这个在下面的代码里面的最里层的两个循环。
代码
class Solution:
def threeSum(self, nums):
result = []
if len(nums) == 0 or len(nums) < 3:
return []
#先对nums排序,然后针对排序的数组进行寻找这样的三元组,排序的目的是为了好在结果返回的时候数组有序
nums.sort()
for index_i in range(0, len(nums)):
point_i = index_i + 1
point_j = len(nums)-1 if index_i != len(nums)-1 else len(nums)-2
#对于相同的值,在上一步计算中已经把所有满足情况的组合加到了结果中,所以下面这里是可以跳过的
if (index_i > 0) and (nums[index_i] == nums[index_i-1]):
continue
while(point_i < point_j):
if nums[point_i] + nums[point_j] + nums[index_i] == 0:
result.append([nums[index_i], nums[point_i], nums[point_j]])
#下面的这两个循环也是为了去掉重复的情况,避免重复的三元组加入到结果中
while(point_i < point_j and nums[point_i]==nums[point_i+1]):
point_i += 1
while (point_i < point_j and nums[point_j] == nums[point_j - 1]):
point_j -= 1
#这两个指针往内走一步是为了除了目前监测到的三元组之外,还有可能还有其他的组合也可以满足相加为0
point_i += 1
point_j -= 1
elif nums[point_i] + nums[point_j] < -nums[index_i]:
point_i += 1
else:
point_j -= 1
return result
if __name__ == '__main__':
solution = Solution()
result = solution.threeSum([-1,0,1,2,-1,-4])
print(result)