39. 组合总和
题目链接:39. 组合总和 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:带你学透回溯算法-组合总和(对应「leetcode」力扣题目:39.组合总和)| 回溯法精讲!哔哩哔哩bilibili
思路:
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
self.candidates = candidates
self.path = []
self.result = []
self.backtrack(0, target)
return self.result
def backtrack(self, start, div):
# 终止条件
if div == 0: # 如果目标值为 0,将当前组合添加到结果列表中并返回
self.result.append(self.path[:])
return
elif div < 0: # 如果目标值为负数,直接返回,不再继续搜索
return
for i in range(start, len(self.candidates)):
self.path.append(self.candidates[i])
self.backtrack(i, div - self.candidates[i])
self.path.pop()
改进:
我们可以先对列表排序,对于有序列表,剪枝效果更好
我们还可以直接传递path变量,而不是作为成员变量,在传递的过程可以采用隐式回溯
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
self.candidates = candidates
self.result = []
self.backtrack(0, target, [])
return self.result
def backtrack(self, start, div, path):
# 终止条件:目标值为 0,将当前组合添加到结果列表中并返回
if div == 0:
self.result.append(path[:])
return
# 递归层
for i in range(start, len(self.candidates)):
# 提前剪枝:如果当前候选数大于目标值,直接跳过
if self.candidates[i] > div:
break
# 递归调用
self.backtrack(i, div - self.candidates[i], path + [self.candidates[i]])
40.组合总和II
题目链接:40. 组合总和 II - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II哔哩哔哩bilibili
思路:
class Solution:
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates.sort()
self.candidates = candidates
self.result = []
self.backtrack(0, target, [])
return self.result
def backtrack(self, start, div, path):
# 终止条件
if div == 0:
self.result.append(path[:])
return
for i in range(start, len(self.candidates)):
# 提前剪枝:如果当前候选数大于目标值,直接跳过
if div < self.candidates[i]:
break
# 避免重复:如果当前候选数和前一个候选数相同,跳过本次循环
if i > start and self.candidates[i] == self.candidates[i - 1]:
continue
self.backtrack(i + 1, div - self.candidates[i], path + [self.candidates[i]])
131.分割回文串
题目链接:131. 分割回文串 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)
视频讲解:带你学透回溯算法-分割回文串(对应力扣题目:131.分割回文串)| 回溯法精讲!哔哩哔哩bilibili
思路:
class Solution:
def partition(self, s: str) -> List[List[str]]:
self.s = s
self.result = []
self.backtrack(0, len(self.s), [])
return self.result
def backtrack(self, start, stop, path):
# 终止条件:
if start == len(self.s):
self.result.append(path[:])
return
# 从当前位置开始向右扩展,检查以当前位置开头的所有子串是否为回文串
for i in range(start,len(self.s)):
# 判断以i为切分点,判断i之前(包含i)的字符串是否为回文串
substring = self.s[start:i+1]
if substring == substring[::-1]:
path.append(substring)
self.backtrack(i+1,len(self.s),path)
path.pop()
感想:这一题后面还要再看看,不是很熟练