力扣第 40 题
题目
给定一个候选人编号的集合 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5]
, target = 8
,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
提示:
1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30
相似问题:
分析
0090 升级版,添加了和的限制。
解答
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
def dfs(i,s):
if i==len(A) or s>=target:
if s==target:
res.append(path[:])
return
dfs(i+1,s)
k,v = A[i]
if v and s+k<=target:
path.append(k)
A[i][1] -= 1
dfs(i,s+k)
path.pop()
A[i][1] += 1
A = [[k,v] for k,v in Counter(candidates).items()]
res, path = [], []
dfs(0,0)
return res
|
41 ms
*附加
同样可以看作背包dp。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
@cache
def dfs(i,s):
if i==len(A):
return [[]] if s==0 else []
k,v = A[i]
res = dfs(i+1,s)[:]
for x in range(1,v+1):
if x*k<=s:
res.extend([k]*x+sub for sub in dfs(i+1,s-x*k))
return res
A = list(Counter(candidates).items())
return dfs(0,target)
|
47 ms