回溯算法
代码模板
思路就是通过横向for循环,纵向递归的形式(递归里面嵌for循环套)
代码模板如下
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择的列表); // 递归
回溯,撤销处理结果
}
}
LeetCode 93.复原IP地址
题目链接
思路
跟131回文字符串有些类似,但我被如何判断是否有效给难住了。。还有一个难点是如何加上“.”并表示出来。一整个被拦住。
思路还是回溯三部曲,每做一个有效的数字出来就加一个“.”,直到分割的4个数都是有效的,就存入result
class Solution:
def restoreIpAddresses(self, s: str) -> List[str]:
result = []
def isValid(s, start, end):
if start > end:
return False
# 若数字是0开头,不合法
if s[start] == '0' and start != end:
return False
if not 0 <= int(s[start:end+1]) <= 255:
return False
return True
def backtracking(s, startIndex, pointNum):
if pointNum == 3:
if isValid(s, startIndex, len(s)-1):
result.append(s)
return
for i in range(startIndex, len(s)):
if isValid(s, startIndex, i):
s = s[:i+1] + '.' + s[i+1:]
backtracking(s, i+2, pointNum+1) #填入.以后要从2位后开始
s = s[:i+1] + s[i+2:]
else:
continue
if len(s) > 12:
return []
backtracking(s, 0, 0)
return result
LeetCode 78.子集
题目链接
思路
标准模板题
class Solution:
def subsets(self, nums: List[int]) -> List[List[int]]:
path = []
result = []
def backtracking(nums, startIndex):
if startIndex == len(nums):
return
for i in range(startIndex, len(nums)):
path.append(nums[i])
result.append(path[:])
backtracking(nums, i+1)
path.pop()
result.append([])
backtracking(nums, 0)
return result
LeetCode 90.子集II
题目链接
思路
跟之前一题去重的逻辑是一样的,用一个标记列表,如果当前数值和上一个相同,且上一个是False的话就直接continue。注意一定要先排序!(第一次写的时候就漏掉了)
class Solution:
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
path = []
result = []
uesd = [False] * len(nums)
nums = sorted(nums) #关键性的一步
def backtracking(nums, startIndex):
if startIndex == len(nums):
return
for i in range(startIndex, len(nums)):
if i>0 and nums[i] == nums[i-1] and uesd[i-1] == False:
continue
else:
path.append(nums[i])
uesd[i] = True
result.append(path[:])
backtracking(nums, i+1)
uesd[i] = False
path.pop()
result.append([])
backtracking(nums, 0)
return result