1.Description:
Given an array nums
of n integers, are there elements a, b, c in nums
such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
The solution set must not contain duplicate triplets.
Example:
Given array nums = [-1, 0, 1, 2, -1, -4], A solution set is: [ [-1, 0, 1], [-1, -1, 2] ]
2.Ideas:
这道题需要从一个列表中选出所有满足和为0的三元组,且要求去重,最简单的思路就是暴力的3层循环,这样肯定会超时。我们可以简单的进行分析,三个数的和为零,可以先确定一个数,然后再确定另外两个数,使另外两个数的和为第一个确定数的相反数,这样就可以将O(n^3)转为O(n^2)。我们可以让第一个确定的数为一个不大于0的数,而且,因为最快的排序算法的时间复杂度是O(nlogn)<O(n^2),因此,我们可以先为列表排序。然后,从第一个开始遍历,最远遍历到倒数第三个,最近遍历到一个正数为止(因为3个大于0的数,和一定也大于0),这个遍历为最外层遍历,注意,这个遍历需要进行去重,即:如果当前位置的值等于下一个位置的值,那么就继续推进。内层循环用来确定另外两个值,循环方式可以选择从首位向中间推进的方式:当首位值相加等于第一个数的相反数时,需要在结果列表中进行添加,然后首尾分别进行推进,并且注意去重;如果首尾值相加小于第一个数的相反数,那么左边向右推进,同时注意去重;如果首尾值相加大于第一个数的相反数,那么右边向左推进,同时注意去重。最终就可以得到全部的结果。
3.Code:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
L = []
nums.sort()
length = len(nums)
if(length<3):
return L
for i in range(length-2):
if(nums[i]>0):#三个大于0的数之和不会是0
break
if(i>0 and nums[i]==nums[i-1]):#去掉重复的情况
continue
target = -nums[i]
left = i+1
right = length-1
while left < right:
if(nums[left]+nums[right]==target):
temp = []
temp.append(nums[i])
temp.append(nums[left])
temp.append(nums[right])
L.append(temp)
left+=1
right-=1
while left<right and nums[left]==nums[left-1]:left+=1
while left<right and nums[right]==nums[right+1]:right-=1
elif(nums[left] + nums[right] <target):
while left < right:
left += 1
if nums[left] > nums[left - 1]: break
else:
while left < right:
right -= 1
if nums[right] < nums[right + 1]: break
return L