40. 组合总和 II
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
所求解集为:
[
[1,2,2],
[5]
]
An understandable python solution:
class Solution(object):
def combinationSum2(self, candidates, target):
"""
:type candidates: List[int]
:type target: int
:rtype: List[List[int]]
"""
candidates.sort()
result = []
self.bfs(candidates, target, 0, [], result)
return result
def bfs(self, nums, target, start, path, result):
if target == 0:
result.append(path)
return
for i in range(start, len(nums)):
if target < nums[i]:
break # early stopping
if i > start and nums[i] == nums[i - 1]:
continue # avoid duplicating
self.bfs(nums, target - nums[i], i + 1, path + [nums[i]], result)
分析:
(1)如果说第39题的“组合总和 I”是DFS,那么本题可以看做是BFS(广度优先搜索)。它们的区别在于DFS尽可能地往深度方向搜索,而BFS尽可能地往广度方向搜索。反映在代码中,就是在每次向下递归时,DFS传递的索引是 i ,而BFS传递的索引是 i+1 。
(2)本题代码中的大部分内容均与第39题相同,除(1)中提到的不同之处外,这里还有另外一个不同之处:因为本题中的数字是有可能包含重复的数字的,这也就意味着如果不做处理,结果中可能会包含有重复的组合。如何解决这一问题呢?代码中的以下判断提供了解决这一问题的一种方法:
if i > start and nums[i] == nums[i - 1]:
continue
如果后面的数字有重复,那就跳过这些重复的数字,从下一个非重复的数字开始继续执行代码。