LeetCode #40 Combination Sum II
题目
解题方法
这题也是典型的排列组合问题,可参考Combination Sum
需要注意的是这道题规定:
- 每个组合不允许重复使用同一位的元素;
- 返回值中不允许出现重复的组合,比如[1, 1, 6]和[1, 6, 1]就是重复的组合。
因此我对应地做了两个调整:
- 修改dfs递归调用时传递的candidate下标为i+1,跳过当前位置;
- 返回之前对嵌套列表ret进行去重操作,去重方法:3Sum。
但实际上可以在dfs的循环体中加一行判断代码,实现在处理过程中去重,省去最后的去重操作,能够显著降低运行时间:
if i > 0 and candidates[i] == candidates[i-1]: continue
代码
返回之前去重
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
ret = []
candidates.sort()
self.dfs(candidates, target, [], ret)
temp_set = set(tuple(i) for i in ret)
new_list = [list(t) for t in temp_set]
return new_list
def dfs(self, candidates: List[int], target: int, path: List[int], ret: List[List[int]]):
if target < 0:
return
if target == 0:
ret.append(path)
return
for i in range(len(candidates)):
if candidates[i] > target:
break
self.dfs(candidates[i+1:], target-candidates[i], path+[candidates[i]], ret)
处理过程中去重
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
ret = []
candidates.sort()
self.dfs(candidates, target, [], ret)
return ret
def dfs(self, candidates: List[int], target: int, path: List[int], ret: List[List[int]]):
if target < 0:
return
if target == 0:
ret.append(path)
return
for i in range(len(candidates)):
if candidates[i] > target:
break
if i > 0 and candidates[i] == candidates[i-1]:
continue
self.dfs(candidates[i+1:], target-candidates[i], path+[candidates[i]], ret)