回溯算法
代码模板
思路就是通过横向for循环,纵向递归的形式(递归里面嵌for循环套)
代码模板如下
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择的列表); // 递归
回溯,撤销处理结果
}
}
LeetCode 39. 组合总和
题目链接
思路
注意组合是没有顺序的 ,例如【2,3】和【3,2】是同一个
这题和77的区别就是,数字可重复
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
path = []
result = []
def backtracking(candidates, target, startIndex):
if sum(path) > target:
return
if sum(path) == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
path.append(candidates[i])
backtracking(candidates, target, i)
path.pop()
backtracking(candidates, target, 0)
return result
LeetCode 40.组合总和II
题目链接
思路
跟39的区别在于,39是同一个位置的数反复用,集合没有重复值,40是同一个位置的数只能用一次但是集合会有重复值
这题的难点是去重的逻辑,要对数值做标记,也就是定义一个标记集合来表示某个数是否被使用过
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
#先做一个排序方便去重
candidates = sorted(candidates)
uesd = [False] * len(candidates)
path = []
result = []
def backtracking(candidates, target, startIndex, uesd):
if sum(path) > target: #剪枝
return
if sum(path) == target:
result.append(path[:])
return
for i in range(startIndex, len(candidates)):
#如果当前元素和上一个取的元素相同,去重
if i>0 and candidates[i] == candidates[i-1] and uesd[i-1] == False:
continue
path.append(candidates[i])
uesd[i] = True
backtracking(candidates, target, i+1, uesd)
uesd[i] = False
path.pop()
backtracking(candidates, target, 0, uesd)
return result
反思
感觉这个去重的逻辑还是不太理解,没明白是怎么想到,如果上一个值标记是0的时候就要跳过本次循环
LeetCode 131.分割回文串
题目链接
思路
依旧是回溯三部曲,需要注意的是存入path的内容前做一个回文判断,先切割判断是回文了再存,不是就直接continue掉
class Solution:
def partition(self, s: str) -> List[List[str]]:
path = []
result = []
def isPalindrome(s, startIndex, i):
s = s[startIndex:i+1]
if s == s[::-1]:
return True
else:
return False
def backtracking(s, startIndex):
if startIndex >= len(s):
result.append(path[:])
return
for i in range(startIndex, len(s)):
if isPalindrome(s, startIndex, i): #拿到的这个字符串是回文的
path.append(s[startIndex:i+1])
backtracking(s, i+1)
path.pop()
else:
continue
backtracking(s, 0)
return result