三数之和
先锁定前两个,第三个游标查后面的,之后再前进第二个游标。到末尾再前进第一个游标。
first submission
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
rList=[]
ai=0
bi=ai+1
ci=ai+2
ll=len(nums)-1
while ci<ll:
c=0-nums[ai]-nums[bi]
while ci<ll:
if nums[ci]==c:
oneList=sorted([nums[ai],nums[bi],nums[ci]])
if oneList not in rList:
rList.append(oneList)
ci+=1
bi+=1
ci=bi+1
return rList
Wrong Answer:
Input:
[0,0,0]
Output:
[]
Expected:
[[0,0,0]]
边界忘了算上
Input:
[3,0,-2,-1,1,2]
Output:
[[-2,-1,3]]
Expected:
[[-2,-1,3],[-2,0,2],[-1,0,1]]
没移动a游标
second submission
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
rList=[]
ai=0
bi=ai+1
ci=ai+2
ll=len(nums)
while ci<ll:
c=0-nums[ai]-nums[bi]
while ci<ll:
if nums[ci]==c:
oneList=sorted([nums[ai],nums[bi],nums[ci]])
if oneList not in rList:
rList.append(oneList)
ci+=1
bi+=1
ci=bi+1
if ci==ll:
# end is move a
ai+=1
bi=ai+1
ci=ai+2
return rList
Time Limit Exceeded:命名为测试点2
Last executed input:
[3,13,8,-8,-15,-3,13,-3,-12,-7,2,-3,-8,10,0,-12,5,13,13,8,6,-11,6,-10,-13,14,-9,9,5,7,12,-14,5,-3,-7,-3,10,13,9,5,13,-4,-12,-9,13,-5,-14,3,-7,6,-12,7,10,10,12,12,9,10,-2,-9,2,-5,-8,14,0,-8,-4,-13,12,12,7,11,-15,2,-13,5,12,10,-14,13,1,-11,-3,-12,14,-6,-15,8,11,-10,7,-10,-7,14,11,8,14,14,10,11,11,-6]
想到笨拙的解法会超时,这么点数据就超时了。现在我的电脑25ms
用了index()在右侧查找第三个数c
,本地时间缩短到8ms
:
third submission
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums=sorted(nums);
rList=[]
ai=0
bi=ai+1
ci=ai+2
ll=len(nums)
while bi<ll-1:
c=0-nums[ai]-nums[bi]
try:
# find c
nums[bi+1:].index(c)
#print('ok')
oneList=sorted([nums[ai],nums[bi],c])
if oneList not in rList:
rList.append(oneList)
except:
#print('error')
pass
bi+=1
if bi==ll-1:
# end is move a
ai+=1
bi=ai+1
return rList
Time Limit Exceeded:
命名为测试点3
Last executed input:
[82597,-9243,62390,83030,...,-97960,-23904,78409,-7418,77916]
1分钟!!摔。有很多数据可以跳过,比如俩负数,下一个肯定得找正的,做了无用功。但我还没想到一个合适的办法。
测试点2,缩小到了 3ms
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums=sorted(nums);
#print(nums)
rList=[]
ai=0
ll=len(nums)
nextc=ll
prevB=0
while ai<ll:
bi=ai+1
if nums[ai]>0:
break
while bi<nextc:
c=0-nums[ai]-nums[bi]
# 负数已完
if c<0 or nums[ai]>0:
break
if c in nums[bi+1:nextc]:
# find c
oneList=sorted([nums[ai],nums[bi],c])
if oneList not in rList:
rList.append(oneList)
nextc=nums.index(c)
#print(nums[bi+1:nextc],nextc)
bi+=1
ai+=1
nextc=ll
return rList
还是太臃肿了,而且最后一个超时节点也过不去。甚至本地都没出来啊。换个类似双指针的思路。
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums=sorted(nums);
#print(nums)
rList=[]
ll=len(nums)
start=0
middle=start+1
end=ll-1
while middle<end:
if nums[start]>0:
break
#print(start,middle,end,[nums[start],nums[middle],nums[end]],0-nums[end]-nums[start]==nums[middle])
if nums[end]+nums[start]<-nums[middle]:
middle+=1
elif nums[start]+nums[middle]>-nums[end]:
end-=1
else:
oneList=sorted([nums[start],nums[middle],nums[end]])
if oneList not in rList:
rList.append(oneList)
middle+=1
end-=1
if middle>=end:
start+=1
middle=start+1
end=ll-1
return rList
测试点2 2.5ms
(对比之前3ms应该算是差不多没有改进),测试点3终于出来了: 4.7s
,还是很长,不敢去测,再想着笨拙的优化一下?提交一下吧,弄不出来了。
依旧超时
看讨论区一个O(N*N)的python解法:
by https://leetcode.com/problems/3sum/discuss/7392/Python-easy-to-understand-solution-(O(n*n)-time).
def threeSum(self, nums):
res = []
nums.sort()
for i in xrange(len(nums)-2):
if i > 0 and nums[i] == nums[i-1]:
continue
l, r = i+1, len(nums)-1
while l < r:
s = nums[i] + nums[l] + nums[r]
if s < 0:
l +=1
elif s > 0:
r -= 1
else:
res.append((nums[i], nums[l], nums[r]))
while l < r and nums[l] == nums[l+1]:
l += 1
while l < r and nums[r] == nums[r-1]:
r -= 1
l += 1; r -= 1
return res
和我的想法差不多,代码都好像啊,试着分析一下为啥我的通不过。只改我认为不同的地方:现在时间4.7-4.8s
- sorted()和list.sort()。
- 暂时不分析排序的不同性能,替换一下也几乎没影响。
- 首先跳过了相等的数字
- 我也添加一个,时间
5.2s
竟然增加了0.4s
耗时
- 我也添加一个,时间
- 将三个值算出来和0做对比
- 这里是应该优化,虽然感觉不重要
spend time: 4.3710356s
少了0.4s
- 这里是应该优化,虽然感觉不重要
- while排除重复的l r 对于我没有作用,不用管
- 添加方式不管才是我为啥费时的原因,他用的元祖不用判断重复,并且append快速。我换了元组之后时间是
spend time: 1.836852s
. 原来可以用元组的,最后测试发现网站自己会转为列表
maybe seventh submission
class Solution:
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
nums=sorted(nums)
rList=[]
ll=len(nums)
start=0
middle=start+1
end=ll-1
while middle<end:
if nums[start]>0:
break
#+ spend time + 0.4s
if start>0 and nums[start] == nums[start-1]:
start+=1
continue
#print(start,middle,end,[nums[start],nums[middle],nums[end]],0-nums[end]-nums[start]==nums[middle])
s=nums[start]+nums[middle]+nums[end]
if s<0:
middle+=1
elif s>0:
end-=1
else:
rList.append((nums[start],nums[middle],nums[end]))
middle+=1
end-=1
if middle>=end:
start+=1
middle=start+1
end=ll-1
return rList
Runtime Error
Runtime Error Message:
Line 16: IndexError: list index out of range
Last executed input:
[0,0,0,0]
再改一下,spend time: 0.3842164
Wrong Answer
Input:
[-2,0,0,2,2]
Output:
[[-2,0,2],[-2,0,2]]
Expected:
[[-2,0,2]]
好吧,外层改成for用start遍历,现在的状态和那个解法就差不离了,提交那个讨论区1s+
的吧 ><
后续:
讨论区还发现一个声称胜过94%的答案,本地0.5s可以参考。用字典存起来每个数字的个数,以便跳过,那两个考虑left right的if我是想不出来的。
by https://leetcode.com/problems/3sum/discuss/155425/beates-94-python3-solution
if len(nums)<3:
return []
if len(nums) == 3 and nums[0] + nums[1] + nums[2] == 0:
return [nums]
nums.sort()
list = []
map = {}
le = len(nums)
for i in nums:
if i in map:
map[i] += 1
else:
map[i] = 1
i = 0
while i < le and nums[i] <= 0:
j = i + 1
left = nums[i]
while j < le:
right = nums[j]
need = 0 - left - right
if need < right:
break
if need not in map:
if left == right:
j += (map[right] - 1)
else:
j += map[right]
continue
if left == right and (need > right or (need == right and map[need] > 2)):
list.append([left, left, need])
j += (map[right] - 1)
elif left != right and ((need == right and map[need] > 1) or need > right):
list.append([left, right, need])
j += map[right]
else:
j += map[right]
i += map[left]
return list