给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。返回 s 所有可能的分割方案。
示例:
输入: “aab”
输出:
[
[“aa”,“b”],
[“a”,“a”,“b”]
]
1 全局变量: 保存结果
2 参数设计: 递归函数的参数,是将上一次操作的合法状态当作下一次操作的初始位置。这里的参数,我理解为两种参数:状态变量和条件变量。(1)状态变量(state)就是最后结果(result)要保存的值;(2)条件变量就是决定搜索是否完毕或者合法的值。
3 完成条件: 完成条件是决定 状态变量和条件变量 在取什么值时可以判定整个搜索流程结束。搜索流程结束有两种含义: 搜索成功并保存结果 和 搜索失败并返回上一次状态。
4 递归过程: 传递当前状态给下一次递归进行搜索。
res = [] # 定义全局变量保存最终结果
state = [] # 定义状态变量保存当前状态
p,q,r # 定义条件变量(一般条件变量就是题目直接给的参数)
def back(状态,条件1,条件2,……):
if # 不满足合法条件(可以说是剪枝,可选)
return
if # 状态满足最终要求(可选)
res.append(state) # 加入结果,必须有
return
# 主要递归过程,一般是带有 循环体 或者 条件体
for # 满足执行条件
if # 满足执行条件
back(状态,条件1,条件2,……)
back(状态,条件1,条件2,……)
return res
由于要求给出具体路径,这里考虑回溯法
这种题目其实有一个通用的解法,模板:
1, 以当前位置为源流往下摸排所有可以跳到的位置
2, 最终递归返回源流位置
3, 然后再以下面一个位置作为源流位置,重复上述操作
全局变量:该题目要找到可分割的方案,最终结果形式上是:[[],[],[],…]
参数设计:(1)状态变量:当前是回文的字符串(2)条件变量:剩余待搜索的字符串,当字符串长度为0,则搜索完毕。
完成条件:剩余字符串长度为0。
递归过程:在剩余字符串中遍历,如果该串为回文 就 进入下次递归,如果非回文 就 继续搜索下一个串。
class Solution:
def partition(self, s: str):
res = [] # 定义全局变量保存最终结果
state = [] # 定义状态变量保存当前状态
n = len(s)
# dp = [[0]*n for _ in range(n)]
# for i in range(n-1, -1, -1):
# dp[i][i] = 1
# for j in range(i+1, n):
# if (s[j] == s[i]) and (j-i<=2):
# dp[i][j] = 1
# elif (s[j] == s[i]) and (dp[i+1][j-1]):
# dp[i][j] = 1
def back(res,state,index):
# 分割问题都需要用到所有元素,要体现到完成条件里面
if index == n:
res.append(state.copy())
return
for i in range(index,n):
# 当i=index的时候,s[index:i+1]=s[index]
# 一个字符就是一个回文串,所以也要添加到状态
# if s[index:i+1] == s[index:i+1][::-1]:
if dp[index][i]:
# 分割问题由于需要用到所有元素,因此用[:xxx]来切片
state = state + [s[index:i+1]]
back(res,state,i+1)
state.pop()
back(res,state,0)
return res
对比leetcode 93 复原ip地址
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
示例 1:
输入:s = “25525511135”
输出:[“255.255.11.135”,“255.255.111.35”]
示例 2:
输入:s = “0000”
输出:[“0.0.0.0”]
示例 3:
输入:s = “101023”
输出:[“1.0.10.23”,“1.0.102.3”,“10.1.0.23”,“10.10.2.3”,“101.0.2.3”]
同样是分割问题
class Solution:
def restoreIpAddresses(self, s: str):
res = [] # 定义全局变量保存最终结果
state = [] # 定义状态变量保存当前状态
n = len(s)
def back(res, state, q):
# 分割问题都需要用到所有元素,要体现到完成条件里面
if (q == n) and (len(state) == 4):
res.append(".".join(state))
return
# 如果没有用到所有元素但是又无法再进行下去,说明这次摸牌失败
# 应该返回nothing
elif (q == n) or (len(state) == 4):
return
# q为ip地址其中一段的起始位,而每一段最多3位,因此可以简化遍历
for i in range(q, min(q + 3, n)):
# 如果一段的第一位是0,则继续扩大是失效的,需要break
if int(s[q]) == 0:
state = state + [s[q]]
back(res, state, q + 1)
state.pop()
break
elif 0 <= int(s[q:i+1]) <= 255:
# 分割问题由于需要用到所有元素,因此用[:xxx]来切片
state = state + [s[q:i+1]]
back(res, state, i + 1)
state.pop()
back(res, state, 0)
return res