对力扣题目“三数之和”的一些思考
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有满足条件且不重复的三元组。
注意:答案中不可以包含重复的三元组。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/3sum
class Solution():
def answer(self,nums):
nums.sort()
result = set()
for i in range(len(nums)):
for j in range(i+1,len(nums)) :
for y in range(j+1,len(nums)):
if nums[i]+nums[j]+nums[y] == 0 :
result.add((nums[i],nums[j],nums[y]))
return list(result)
# 315/318 over time ...
先循环一个,然后两个指针在剩余的数中分别由ZUO 右向中间汇集:
class Solution():
def answer(self,nums):
nums.sort()
result = set()
for i in range(len(nums)-2):
p = i+1
q = len(nums) - 1
while q > p :
if nums[i] + nums[p] + nums[q] == 0 :
result.add((nums[i],nums[p],nums[q]))
if nums[i] + nums[p] + nums[q] < 0 :
p += 1
else :
q -=1
return list(result)
# Run time: 4104ms Memory consump:16.7MB
这个写的有点糙,看完这个答案之后:
链接:https://leetcode-cn.com/problems/3sum/solution/pai-xu-shuang-zhi-zhen-zhu-xing-jie-shi-python3-by/
作者:wu_yan_zu
基于原来写出的加了一些判断条件,从而在明知后面无解的情况下,不再继续循环:
class Solution():
def answer(self,nums):
nums.sort()
result = set()
for i in range(len(nums)-2):
if nums[i] > 0 :
return list(result)
#排序之后,起始值都大于零,那么后面肯定无解
if (i>0 and nums[i]==nums[i-1]):
continue
#意在去重
p = i+1
q = len(nums) - 1
while q > p :
if (nums[i] + nums[p] + nums[q]) == 0 :
result.add((nums[i],nums[p],nums[q]))
while (q > p) and (nums[q] == nums [q-1]):
q -= 1
while (q > p) and (nums[p] == nums [p+1]):
p += 1
#去重
p += 1
q -= 1
elif nums[i] + nums[p] + nums[q] > 0 : #确定指针移动方向
q -= 1
else :
p +=1
return list(result)
#Run time:820ms Mermory consump: 16.8MB
改动之后的运行时间和参考的差不多,但改动之后的内存占用略少.
尝试两个循环,一个指针:
class Solution():
def answer(self,nums):
nums.sort()
result = set()
for i in range(len(nums)-2):
if nums[i] > 0 :
return list(result)
for j in range(i+1,len(nums)-1):
q = len(nums) - 1
now = nums[i] + nums[j]
if now > 0:
break
while q > j :
if now + nums[q] == 0 :
result.add((nums[i],nums[j],nums[q]))
q -= 1
if now + nums[q] > 0 :
q -= 1
else :
break
return list(result)
# 315/318 over time ....
这个好像也是立方次的时间复杂度。
仿照上一篇的两数之和的递归,很容易照猫画虎把三数之和的递归写出来:
class Solution():
def answer(self,nums):
nums.sort()
result = []
def find(i,target,oneSolution,notSelected):
if len(oneSolution) == 3 and target == 0:
result.append(oneSolution)
return
if i >= len(nums) or len(oneSolution) > 3 :
return
if target - nums[i] - (2-len(oneSolution))*nums[-1] > 0 or nums[i] in notSelected :
find(i+1,target,oneSolution,notSelected)
elif target - (3-len(oneSolution))*nums[i] < 0 :
return
else:
find(i+1,target,oneSolution,notSelected+[nums[i]])
find(i+1,target-nums[i],oneSolution+[nums[i]],notSelected)
find(0,0,[],[])
return result
# 315/318 over time...
然而也超时了。
不知道是不是我中间判断条件有缺少思考的地方,如果有看出来的大神们,还请不吝赐教。
三数之和虽然看起来和二数之和很类似,但是它们之间的差异还是蛮大的。