题目
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
链接:https://leetcode.com/problems/combination-sum-ii/
Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.
Each number in candidates may only be used once in the combination.
Note:
- All numbers (including target) will be positive integers.
- The solution set must not contain duplicate combinations.
Example:
Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
思路及代码
1.
- Recursive
- 主要思路同39题
- 在最后利用set()对嵌套列表list of list去重(代码中注释掉的那一行)
- 在过程中用set()去重,可以降低ans的空间复杂度:把cur转化为tuple后加入ans这个set里,因为set里不能加list,只能加tuple
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
cur = []
ans = set()
candidates = sorted(candidates)
def dfs(candidates, target, start, cur, ans):
if target == 0:
l = tuple(cur)
ans.add(l)
return
for i in range(start, len(candidates)):
if candidates[i] > target:
break
cur.append(candidates[i])
dfs(candidates, target - candidates[i], i+1, cur, ans)
cur.pop()
dfs(candidates,target,0,cur,ans)
ans = [list(_) for _ in ans]
# ans = [list(i) for i in set(tuple(_) for _ in ans)]
return ans
2.
- 对于组合中相同深度的位置,同样的数字只用一次
代码主要改变在:
if i > start and candidates[i] == candidates[i-1]:
continue
完整代码:
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
cur = []
ans = []
candidates = sorted(candidates)
def dfs(candidates, target, start, cur, ans):
if target == 0:
l = cur.copy()
ans.append(l)
return
for i in range(start, len(candidates)):
if candidates[i] > target:
break
if i > start and candidates[i] == candidates[i-1]:
continue
cur.append(candidates[i])
dfs(candidates, target - candidates[i], i+1, cur, ans)
cur.pop()
dfs(candidates,target,0,cur,ans)
return ans
复杂度
T = O(
n
∗
2
n
n*2^n
n∗2n)
可以将每一个元素看成0-1的选择题,有或者无,所以最多一共有2^n个子集。
S = O(kn), k 为组合的数目