题目:
给你一个 无重复元素 的整数数组 candidates
和一个目标整数 target
,找出 candidates
中可以使数字和为目标数 target
的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates
中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target
的不同组合数少于 150
个。
提示:
1 <= candidates.length <= 30
2 <= candidates[i] <= 40
candidates
的所有元素 互不相同1 <= target <= 40
思考:
因为要找到所有和为target的组合,可以构建一棵树,根节点为target,每条路径的值为candidates中的数,路径连接的子节点即为 父节点-路径值 ,保证只有所有叶子节点的值为0(从根节点到叶子节点0的路径即为所求的一个组合)或小于0(这条路径代表的组合不能满足和为target的条件)。以示例1为例,上述思路如下图所示:
可以看到找出了所有满足条件的组合,代码如下:
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
n = len(candidates)
ans = []
candidates.sort()
def makeTree(target, candidates, path, ans):
if target < 0:
return
elif target == 0:
ans.append(path)
return
else:
for index in range(0, n):
makeTree(target - candidates[index], candidates, path + [candidates[index]], ans)
makeTree(target, candidates, [], ans)
return ans
但是可以看到结果中出现了顺序不同,但元素完全相同的组合,但题目中说明这种组合是同样的,不应该重复返回。在图中用绿色表示应该删去的分支:
可以总结出:每一层的第二个节点生成子节点的路径值不能使用生成他的前序兄弟节点的路径值。
这样就避免了重复组合的出现,代码如下:
class Solution(object):
def combinationSum(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
n = len(candidates)
ans = []
candidates.sort()
def makeTree(target, candidates, path, ans, begin_index):
if target < 0:
return
elif target == 0:
ans.append(path)
return
else:
for index in range(begin_index, n):
makeTree(target - candidates[index], candidates, path + [candidates[index]], ans, index)
makeTree(target, candidates, [], ans, 0)
return ans
提交通过: