2020/3/19 打卡
给定一个数组 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]
]
这里有个 主要的问题是 ‘candidates 中的每个数字在每个组合中只能使用一次’,所以这里很大的牵扯到去重的问题。
本题难点:candidates=[1,7,1],target=8,,,那么[1,7]和[7,1]重复
使用回溯+剪枝的算法。 在三步走过程中,融入对两步剪枝操作的判别。
1.特判,若candidates为空,则返回[]
2.回溯函数helper(),传入参数:下一加和索引ii,当前已加和数组tmp,下一目标target
(1)若target==0,说明当前和满足条件,将当前加和数组tmp加入res,并return。
(2)剪枝 因为已经将candidates排序,所以当下一目标小于下一待加和数时,return。
并且当下一待加和索引i==n时,return。(为了防止数组越界,将条件i==n放在targetiandcandidates[j]==candidates[j−1](为了防止数组越界,首先保证j>i,判断是否和
上一元素相等),分为以下两种情况:
*若满足条件j>i and candidates[j]==candidates[j-1],则跳过,避免出现重复解,同时也进行了剪枝。
*否则,执行helper(j+1,tmp+[candidates[j]],target−candidates[j])
3.执行helper(0,[],target),并返回res
时间复杂度:O(n!) 空间复杂度:O(n)
class Solution:
def combinationSum2(self, candidates, target):
# 边界条件
if(not candidates):
return []
# 进行预排序操作
n=len(candidates)
candidates.sort()
res=[]
def helper(i,tmp,target):
# 当前和满足条件,将当前加和数组tmp加入res,并return
if(target==0):
res.append(tmp)
return
# 对于 越界操作 无效解的去除。 因为是排序过的,所以可以直接判别出 余值的满足情况。
if(i==n or targeti and candidates[j]==candidates[j-1]):
continue
# i是新的dfs的起点, tmp存储暂时路径,最后是余值。
helper(j+1,tmp+[candidates[j]],target-candidates[j])
# 外部调动dfs搜索。
helper(0,[],target)
return res