第七章 回溯算法part01
理论基础
其实在讲解二叉树的时候,就给大家介绍过回溯,这次正式开启回溯算法,大家可以先看视频,对回溯算法有一个整体的了解。
题目链接/文章讲解:代码随想录
视频讲解:带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili
77. 组合
对着 在 回溯算法理论基础 给出的 代码模板,来做本题组合问题,大家就会发现 写回溯算法套路。在回溯算法解决实际问题的过程中,大家会有各种疑问,先看视频介绍,基本可以解决大家的疑惑。
本题关于操作是大家要理解的重点,因为后面很多回溯算法解决的题目,都是这个剪枝套路。
题目链接/文章讲解:代码随想录
视频讲解:带你学透回溯算法-组合问题(对应力扣题目:77.组合)| 回溯法精讲!_哔哩哔哩_bilibili
剪枝操作:带你学透回溯算法-组合问题的剪枝操作(对应力扣题目:77.组合)| 回溯法精讲!_哔哩哔哩_bilibili
# 77
class Solution(object):
def combine(self, n, k):
"""
:type n: int
:type k: int
:rtype: List[List[int]]
"""
self.path = []
self.result = [] # 存放结果集
self.backtracking(n, k, 1)
return self.result
def backtracking(self, n, k, startIndex):
if len(self.path) == k:
self.result.append(self.path[:])
return
for i in range(startIndex, n - (k - len(self.path)) + 2): # 优化的地方
self.path.append(i) # 处理节点
self.backtracking(n, k, i + 1)
self.path.pop() # 回溯,撤销处理的节点
216.组合总和III
如果把 组合问题理解了,本题就容易一些了。
题目链接/文章讲解:代码随想录
视频讲解:和组合问题有啥区别?回溯算法如何剪枝?| LeetCode:216.组合总和III_哔哩哔哩_bilibili
# 216
class Solution(object):
def combinationSum3(self, k, n):
"""
:type k: int
:type n: int
:rtype: List[List[int]]
"""
self.path = []
self.result = [] # 存放结果集
self.backtracking(n, k, 0, 1)
return self.result
def backtracking(self, targetSum, k, currentSum, startIndex):
if currentSum > targetSum: # 剪枝1
return
if len(self.path) == k:
if currentSum == targetSum:
self.result.append(self.path[:])
return
for i in range(startIndex, 9 - (k - len(self.path)) + 2): # 剪枝2
currentSum += i # 处理
self.path.append(i) # 处理
self.backtracking(targetSum, k, currentSum, i + 1) # 注意i+1调整startIndex
currentSum -= i # 回溯
self.path.pop() # 回溯
17.电话号码的字母组合
本题大家刚开始做会有点难度,先自己思考20min,没思路就直接看题解。
题目链接/文章讲解:代码随想录
视频讲解:还得用回溯算法!| LeetCode:17.电话号码的字母组合_哔哩哔哩_bilibili
# 17
class Solution(object):
def __init__(self):
self.letterMap = [
"", # 0
"", # 1
"abc", # 2
"def", # 3
"ghi", # 4
"jkl", # 5
"mno", # 6
"pqrs", # 7
"tuv", # 8
"wxyz" # 9
]
self.result = []
self.s = ""
def backtracking(self, digits, index):
if index == len(digits):
self.result.append(self.s)
return
digit = int(digits[index]) # 将索引处的数字转换为整数
letters = self.letterMap[digit] # 获取对应的字符集
for i in range(len(letters)):
self.s += letters[i] # 处理字符
self.backtracking(digits, index + 1) # 递归调用,注意索引加1,处理下一个数字
self.s = self.s[:-1] # 回溯,删除最后添加的字符
def letterCombinations(self, digits):
"""
:type digits: str
:rtype: List[str]
"""
if len(digits) == 0:
return self.result
self.backtracking(digits, 0)
return self.result