39. 组合总和
无重复元素,但是同一个数字可以被重复选取,因此在参数中startIndex在每次递归时不需要+1。但是要注意,为了不寻找之前已经找过的元素,startIndex需要加上,表示只会继续向前寻找
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result = []
self.backtracking(candidates, target, result, [], 0, 0)
return result
def backtracking(self, candidates, target, result, path, curSum, startIndex):
if curSum > target:
return
if curSum == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
path.append(candidates[i])
self.backtracking(candidates, target, result, path, curSum+candidates[i], i)
path.pop()
剪枝
其实就是将下一层的sum大于target的终止条件放到本层的for循环中
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
result = []
self.backtracking(candidates, target, result, [], 0, 0)
return result
def backtracking(self, candidates, target, result, path, curSum, startIndex):
if curSum == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
if curSum+candidates[i] > target:
continue
path.append(candidates[i])
self.backtracking(candidates, target, result, path, curSum+candidates[i], i)
path.pop()
40.组合总和II
有重复元素,只能被使用一次,结果需要去重
不去重的代码如下
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
result = []
self.backtracking(candidates, target, result, [], 0, 0)
return result
def backtracking(self, candidates, target, result, path, curSum, startIndex):
if curSum == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
if curSum + candidates[i] > target:
break
path.append(candidates[i])
self.backtracking(candidates, target, result, path, curSum+candidates[i], i+1)
path.pop()
去重可以使用used数组进行标记
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
result = []
used = [False] * len(candidates)
self.backtracking(candidates, target, result, [], 0, 0, used)
return result
def backtracking(self, candidates, target, result, path, curSum, startIndex, used):
if curSum == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
if curSum + candidates[i] > target:
break
if i > 0 and candidates[i] == candidates[i-1] and used[i-1] == False:
continue
path.append(candidates[i])
used[i] = True
self.backtracking(candidates, target, result, path, curSum+candidates[i], i+1, used)
path.pop()
used[i] = False
也可以不使用数组,直接使用索引进行去重
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
result = []
self.backtracking(candidates, target, result, [], 0, 0)
return result
def backtracking(self, candidates, target, result, path, curSum, startIndex):
if curSum == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
if curSum + candidates[i] > target:
break
if i > startIndex and candidates[i] == candidates[i-1]:
continue
path.append(candidates[i])
self.backtracking(candidates, target, result, path, curSum+candidates[i], i+1)
path.pop()
131.分割回文串
class Solution:
def partition(self, s: str) -> List[List[str]]:
result = []
self.backtracking(s, result, [], 0)
return result
def backtracking(self, s, result, path, startIndex):
if startIndex >= len(s):
result.append(path[:])
return
for i in range(startIndex, len(s)):
if self.is_palindrome(s, startIndex, i):
path.append(s[startIndex:i+1])
else:
continue
self.backtracking(s, result, path, i+1)
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
注:求是否为回文串的代码存在优化的空间