class Solution:
def backtracking(self, candidates, target, total, startIndex, path, result):
if total > target:
return
if total == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
total += candidates[i]
path.append(candidates[i])
self.backtracking(candidates, target, total, i, path, result)
total -= candidates[i]
path.pop()
def combinationSum(self, candidates, target):
result = []
self.backtracking(candidates, target, 0, 0, [], result)
return result
观察题目要求可知:1.组合中的元素可以无限制重复---因此,此题和以往的题目区别已经显现。我们在进行树结构的绘制的时候,所规定的index便不需要+1,因为元素可以重复。
2.绘制树结构,按照回溯流程进行解题,顺利写出代码即可。
class Solution:
def backtracking(self,total,target,startIndex,candidates,used,path,result):
if total > target:
return
if total == target:
result.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 #此时进入树枝层
total += candidates[i]
path.append(candidates[i])
used[i] = True
self.backtracking(total,target,i + 1,candidates,used,path,result)
used[i] = False
total -= candidates[i]
path.pop()
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
used = [False] * len(candidates)
candidates.sort()
result = []
self.backtracking(0,target,0,candidates,used,[],result)
return result
在审题时,虽然注意到了题目的意思是在candidates中每个数字在集合中值出现一次,存在candidates中元素重复情况的存在,但是在解题时还是掉进了该陷阱中。归纳来讲就是---有重复元素没有重复组合。针对于该题目,我们首先需要的就是对于数组进行排序,使得在树结构的同一层中不存在重复元素, 在叶子结点可以有相同元素,这样可以防止重复组合的出现。
代码中:used使用布尔型进行判断,方便我们后续进行if判断和去重操作。
在全局变量中要事先分配used空间,然后再进行去重操作。
在该题中,比较抽象的就是在进行去重,如何去重以及去重什么?怎样针对性的进行去重?我将以绘制树结构来进行阐述。
candidates[i]==candidates[i-1]:说明前后有两个元素相同,此时会产生两种情况。 一种是在树层上get-1,另一种是在树枝上 get-1;此时我们需要想到,要保留树枝,去重树层,利用used来去重即可。used[i-1]==0说明在树层层面。
class Solution:
def partition(self, s: str) -> List[List[str]]:
result = []
self.backtracking(s,0,[],result)
return result
def ispartition(self,s,startIndex,i):
if s[startIndex:i+1] == s[startIndex:i+1][::-1]:
return True
else:
return False
def backtracking(self,s,startIndex,path,result):
if startIndex == len(s):
result.append(path[:])
return
for i in range(startIndex,len(s)):
if self.ispartition(s,startIndex,i):
path.append(s[startIndex:i+1])
self.backtracking(s,i+1,path,result)
path.pop()
return result
回溯类型中的新题型---分割问题。
绘制树结构,发现答题思路和组合问题相似,借助图像帮忙理解该问题:
1.切割,切割后的字符串后期仍需用到;所切割的位置也要进行标记。
2.所保留的结果均在叶子结点。
明确理解,在树结构中“|”就是我们在代码中所提到的startIndex。
依照回溯三部曲:终止条件:当分割线在字符串末尾终止;收集结果,一维数组加入二维数组中;所需遍历的元素集:所包含的字符串区间,用startIndex和i进行标记。处理节点:进行回文数的判断,需要再定义函数。递归和回溯操作和组合相同。