题目描述:找出任意三个数和为0的子集合,并列出出来,不可有重复。
题目链接:Leetcode 15. 3Sum
用递归的做法在31就超时了,一共313个case。
一般数组的题目要想加速 就要额外空间 hashmap做记忆或者两个指针的办法,一定要学会转化问题。
待定一个数 找这个数之后的数组所有不重复两个数相加和为此数的组合。
如果sum改成其他的数 只需要把求fix的步骤改一下就好了。
代码如下
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums.sort()
if len(nums) < 3:
return []
ans = []
for i in range(0,len(nums)-2): #到最后两个就停下
fix = 0 - nums[i] #需要fix的数 如果和前面一个数字相等 则continue
if (i > 0 and nums[i] == nums[i-1]): #去重
continue
l = i + 1 #fix 数的下一个数 开始查询[l,r] 两个数相加和为 fix,注意去重。
r = len(nums) - 1 #需要fix的数的右边数组的右边界
while(l < r): #当左边界小于右边界时
curr_sum = nums[l] + nums[r]
if (curr_sum > fix): #太大了则右边往左
r -= 1
elif (curr_sum < fix): # 太小了往右
l += 1
else:
ans.append([-fix,nums[l],nums[r]])
l += 1
r -= 1 # 此时继续寻找 因为仍然有可能
while(l < r and nums[l] == nums[l-1]):
l += 1 #跳过此l重复了
while(l < r and nums[r] == nums[r+1]): #更原来
r -= 1 #跳过这个r重复了
return ans
class Solution:
#超时代码
def threeSum(self, nums: List[int]) -> List[List[int]]:
ans = []
self.dfs(nums,ans,[],0)
return ans
def dfs(self,nums,ans,path,start):
if len(path) > 3:
return
if (sum(path) == 0 and len(path) == 3):
path.sort()
if path not in ans:
ans.append(path)
return
for i in range(start,len(nums)):
self.dfs(nums,ans,path+[nums[i]],i+1) #选
self.dfs(nums,ans,path,i+1) # 不选