39. 组合总和
给你一个 无重复元素 的整数数组 candidates
和一个目标整数 target
,找出 candidates
中可以使数字和为目标数 target
的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates
中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target
的不同组合数少于 150
个。
解题思路:
注意本题同一个 数字可以 无限制重复被选取,但是要明确的是进入下一层for循环时,可选的option是从自身开始,不是从第一个数开始否则会有重复,如下
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result= []
path = []
start = 0
def backtracking(candidates, target, start, total, result, path):
if total == target:
result.append(path[:])
print(result)
return
if total > target:
return
for i in range(len(candidates)):
#注意此处应该从range(start, len(candidates))开始选取,从自身index开始不包含前面
total += candidates[i]
path.append(candidates[i])
backtracking(candidates, target, i, total, result, path)#从i index开始
total -= candidates[i]
path.pop()
backtracking(candidates, target, start, 0, result, path)
return result
[[2, 2, 3]]
[[2, 2, 3], [2, 3, 2]]
[[2, 2, 3], [2, 3, 2], [3, 2, 2]]
[[2, 2, 3], [2, 3, 2], [3, 2, 2], [7]]
正确代码应如下
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result= []
path = []
start = 0
def backtracking(candidates, target, start, total, result, path):
if total == target:
result.append(path[:])
print(result)
return
if total > target:
return
for i in range(start, len(candidates)):
total += candidates[i]
path.append(candidates[i])
backtracking(candidates, target, i, total, result, path)
total -= candidates[i]
path.pop()
backtracking(candidates, target, start, 0, result, path)
return result
40.组合总和II
给定一个候选人编号的集合 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
解题思路:
本体要注意去重,在数层方面除去重复的数字,比如[1,1,2], 第一个数和第二个数是一样的,如果不排除第二个一样的数字会导致出现重复组合,并且遍历逻辑可得是在for loop进行到下一个数字的时候进行判断。
输入参数:def backtracing(candidates, start, result, path, targetsum, sum)
停止条件:if targetsum<sum: return; if targetsum == sum: result append
递归逻辑:for i in range(start_index, len(candidates)): if targetsum == sum and i>start: continue
backtracing(candidates, i+1, result, path, targetsum, sum)
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
path = []
result = []
sum = 0
candidates = sorted(candidates)
def backtracking(candidates, path, result, start_index, sum, target):
if sum == target:
result.append(path[:])
return
if sum>target:
return
for i in range(start_index, len(candidates)):
if i>start_index and candidates[i] == candidates[i-1]:
continue#skip
if sum + candidates[i]>target:
break
sum += candidates[i]
path.append(candidates[i])
backtracking(candidates, path, result, i+1, sum, target)
sum -= candidates[i]
path.pop()
backtracking(candidates, path, result, 0, sum, target)
return result
131.分割回文串
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是 回文串。返回 s
所有可能的分割方案。
解题思路:
本题再添加进path之前要判断是否为回文子串,使用start_index作为切割点,start_index=0时表示未进行切割。
输入参数:def backtracking(s, start_index, path, result)
停止条件:if len(s) >= start_index
回溯逻辑:检查是否为回文子串,是的话path.append(s[start_index:i+1])
class Solution:
def partition(self, s: str) -> List[List[str]]:
path = []
result = []
def backtracking(s, start_index, path, result):
#stopping at start_index>=len
if start_index>= len(s):
result.append(path[:])
return
for i in range(start_index, len(s)):
#判断回文子串
if s[start_index:i+1] != s[start_index:i+1][::-1]:
continue
path.append(s[start_index:i+1])
backtracking(s, i+1, path, result)
path.pop()
backtracking(s, 0, path, result)
return result