39. 组合总和
力扣链接
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
说明:
所有数字(包括 target)都是正整数。
解集不能包含重复的组合。
思路
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res = []
self.backtracking(candidates, target, 0, 0, [], res)
return res
def backtracking(self, candidates, target, cur_sum, startIndex, path, res):
if cur_sum > target:
return
if cur_sum == target:
res.append(path[:]) #一定记得[:]
return
for i in range(startIndex,len(candidates)):
cur_sum += candidates[i]
path.append(candidates[i])
self.backtracking(candidates, target, cur_sum, i, path, res)#startIndex用i表示可以重复读取
cur_sum -= candidates[i]
path.pop() #回溯
40.组合总和II
力扣链接
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。
思路
同一层上的相同元素不能重复用,用一个used数组记录每个元素的使用情况。
如果candidates[i] == candidates[i - 1] 并且 used[i - 1] == false,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]。
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
used = [False] * len(candidates)
res = []
candidates.sort()
self.backtracking(candidates, target, 0, 0, used, [], res)
return res
def backtracking(self, candidates, target, total, startIndex, used, path, res):
if total == target:
res.append(path[:])
return
for i in range(startIndex, len(candidates)):
# 对于相同的数字,只选择第一个未被使用的数字,跳过其他
if i > startIndex and candidates[i]==candidates[i-1] and not used[i-1]:
continue
if total + candidates[i] > target:
break
total += candidates[i]
path.append(candidates[i])
used[i] = True #标记为用过
self.backtracking(candidates, target, total, i+1, used, path, res)
#回溯
used[i]=False
total -= candidates[i]
path.pop()
131.分割回文串
力扣链接
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串。返回 s 所有可能的分割方案。
思路
class Solution:
def partition(self, s: str) -> List[List[str]]:
res = []
self.backtracking(s, 0, [], res)
return res
def backtracking(self, s, startIndex, path, res):
if startIndex == len(s):
res.append(path[:])
return
for i in range(startIndex, len(s)):
if self.is_palindrome(s, startIndex, i): # 如果是回文
path.append(s[startIndex : i+1])
self.backtracking(s, i+1, path, res)
path.pop()
def is_palindrome(self, s, start, end):
while start < end:
if s[start] != s[end]:
return False
start += 1
end -= 1
return True