最开始的思路,是希望尽量不要重复遍历,第一次的解法是:
def threeSum(nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
if nums[0] > 0:
return []
elif nums[len(nums)-1] < 0:
return []
else:
result = list()
head = 0
tail = len(nums)-1
ind = 0
for i in range(head,tail+1):
if nums[i]>=0:
ind = i
break
while head <= ind <= tail:
if nums[head]+nums[tail] > 0 or ind == tail:
for i in range(ind, head, -1):
if nums[head]+nums[tail] + nums[i] == 0:
result.append([nums[head],nums[tail],nums[i]])
head = head + 1
break
elif nums[head]+nums[tail] + nums[i] < 0:
head = head + 1
break
tail = tail - 1
elif nums[head]+nums[tail] < 0:
for i in range(ind, tail):
if nums[head]+nums[tail] + nums[i] == 0:
result.append([nums[head],nums[tail],nums[i]])
tail = tail - 1
break
elif nums[head]+nums[tail] + nums[i] > 0:
tail = tail - 1
break
head = head + 1
else:
if nums[ind] == 0:
result.append([nums[head], 0, nums[tail]])
if nums[head] == num[tail]:
break
else:
head = head + 1
return result
逻辑:县排序,前面特殊情况判断不解释,后面,当正数(tail)比负数(head)大时,从负数处找另一个解,即 for i in range(ind, head, -1):
ind为中间数,从中间遍历可以尽早找到解(如果有的话),当二者相加小于等于0时,没有继续向前遍历的意义了,就终止,head向后挪一位,这个较大的正数(tail)与所有可能的两个负数遍历完之后,tail-1。正数比负数小时,同理。
但是这种方法始终存在覆盖不了的情况(一脸懵逼= =跪求指点,等我想出是哪里出问题再来更新)
放弃第一种解法之后,开始妥协遍历的重复率,第二种解法:
class Solution:
def threeSum(self,nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums.sort()
if len(nums) < 3:
return []
left = 0
right = len(nums)-1
result = []
while nums[left] <= 0 and left < right:
while nums[right] >= 0 and left < right:
if nums[right] + nums[left] > 0:
n = left + 1
while nums[n] < 0 and nums[right] + nums[left] + nums[n] <= 0:
if nums[right] + nums[left] + nums[n] == 0 and [nums[left], nums[n], nums[right]] not in result:
result.append([nums[left], nums[n], nums[right]])
n = n + 1
elif nums[right] + nums[left] < 0:
n = right - 1
while nums[n] > 0 and nums[right] + nums[left] + nums[n] >= 0:
if nums[right] + nums[left] + nums[n] == 0 and [nums[left], nums[n], nums[right]] not in result:
result.append([nums[left], nums[n], nums[right]])
n = n - 1
else:
n = left + 1
while nums[n] <= 0 and n < right:
if nums[n] == 0 and [nums[left], nums[n], nums[right]] not in result:
result.append([nums[left], nums[n], nums[right]])
n = n+1
right = right -1
right = len(nums) - 1
left = left + 1
return result
逻辑:对每个负数(下标left),寻找一个正数right,和一个中间数(n),n的取值范围根据left和right的大小来决定。但此方法提交会超时(3层循环)
最终采用答案里的解法:
class Solution:
def threeSum(self,nums):
result={}
nums.sort()
for i,num in enumerate(nums):
left = i + 1
right = len(nums) - 1
while left < right:
s = nums[i] + nums[left] + nums[right]
if s < 0 :
left+=1
elif s > 0:
right-=1
else:
if (nums[i], nums[left], nums[right]) not in result:
result[(nums[i], nums[left], nums[right])] = 1
if nums[left] == nums[right]:
break
left+=1
right-=1
return list(result.keys())
逻辑:对每个数向右找两位能相加为0的数,遍历整个数组。答案通过(只有两层循环)