方法一:排序+双指针
根据题目特点选择方法:
1. 枚举的三元组(a,b,c) ,满足a<=b<=c,保证了只有 (a,b,c) 这个顺序会被枚举到,而(b,a,c)、(c,b,a) 等等这些不会,这样就减少了重复。要实现这一点,我们可以将数组中的元素从小到大进行排序,随后使用普通的三重循环就可以满足上面的要求。
2. 需要枚举数组中的两个元素时,如果我们发现随着第一个元素的递增,第二个元素是递减的,那么就可以使用双指针的方法
大概思路:
1.由于需要求和为0的不重复的三数和,因此数据中有负数,也有正数(除非全0)
2.因此将负数放数据的左边,整数放在数组的右边,由小到大(排序)
3.固定一个数,使用双指针分别寻找和为0的两外两个数据(当和小于0,说明需要增大数据来使和为0,left+1,否者需要减小数据,right-1)
具体细节参看代码:
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
n=len(nums)
if (not nums or n<3):
return []
nums.sort()
ret=[]
for i in range(n):
if (nums[i]>0): #假设所有的数组元素都大于0,则没有和为0的三个数
return ret
if (i>0 and nums[i]==nums[i-1]):#排除i指向的数据的重复性,i位置重复,和的另外两个数据也会重复
continue
left=i+1
right=n-1
while(left<right):#通过调节左右两指针所指向的数据来调节三数之和(固定i指向的数字,再调节左大右小,左小右大)
if (nums[i]+nums[left]+nums[right]==0):#当和为0时
ret.append([nums[i],nums[left],nums[right]])
while (left<right and nums[left]==nums[left+1]):#去除left处重复的数组元素(因为返回的数组必须是不重复的)
left=left+1
while (left<right and nums[right]==nums[right-1]):#去除right处重复的数组元素(左右元素只要一个与上一轮重复,则另外一个必定重复)
right=right-1
left -= 1 #不断循环left
right-= 1
elif (nums[i]+nums[left]+nums[right]<0):#和小于0,说明需要有一个数据增大来使数等于0,调节左边指针
left+=1
else:#和小于0,说明需要有一个数减小来使数等于0,调节右边指针
right-=1
return ret