剪枝操作就是,在暴力破解下减少计算量。
39. 组合总和
class Solution:
def backtracking(self, candidates, target, path, res, startIndex, cursum):
if cursum > target: # 排序后:cursum>targe之后的元素都可以不去算了(break出循环)
return
if cursum == target:
res.append(path[:])
return
for i in range(startIndex, len(candidates)):
cursum += candidates[i]
if cursum > target:
break
path.append(candidates[i])
self.backtracking(candidates, target, path, res, i,cursum)
path.pop()
cursum -= candidates[i]
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
res = []
candidates.sort()
self.backtracking(candidates, target,[], res,0,0)
return res
40. 组合总和 II
同一个组合内可以有相同的元素,就是同一个树枝里面是允许重复的;不能有相同的组合,就是同一层不能有重复元素。
实现的方式很巧妙,记录一个used,只有在同一个树枝的情况下才能继续递归,不同树枝就continue了。比把全部的组合都找出来节约时间。虽然把全部的组合找出来的时候可以在过程中去重,但是需要把每个树枝就去找一遍,多了很多递归。
class Solution:
def backtracking(self, candidates, used, target, path, res, cursum,startIndex):
# if cursum > target: # 有了剪枝2之后,这个可以不用了
# return
if cursum == target:
res.append(path[:])
for i in range(startIndex, len(candidates)):
if i>startIndex and candidates[i] == candidates[i-1] and not used[i-1]: # 剪枝1
continue
cursum += candidates[i]
if cursum > target: # 剪枝2
break
path.append(candidates[i])
used[i]=True
self.backtracking(candidates, used, target,path,res,cursum,i+1)
used[i]=False
path.pop()
cursum -= candidates[i]
# while i > 0 and candidates[i] == candidates[i-1]:
# i += 1
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
# 排好序
# 先能找出所有符合条件元组
# 再考虑剪枝去重
candidates.sort()
# print(candidates)
res = []
used = [False]*len(candidates)
self.backtracking(candidates, used, target, [], res,0,0)
return res
131. 分割回文串
剪枝:当从startindex到目前的位置不是回文的时候,不进入递归
class Solution:
def isHuiwen(self,text):
left, right = 0, len(text) -1
while left < right:
if text[left:left+1] != text[right:right+1]:
return False
left += 1
right -= 1
return True
def backtracking(self,s,startIndex,res,path):
# 什么时候终止?
if startIndex == len(s):
res.append(path[:])
return
for i in range(startIndex, len(s)):
if self.isHuiwen(s[startIndex: i+1]):
path.append(s[startIndex: i+1])
self.backtracking(s,i+1, res, path)
path.pop()
def partition(self, s: str) -> List[List[str]]:
# 先把回文判断搞定
res = []
self.backtracking(s,0,res,[])
return res