原题链接:https://leetcode-cn.com/problems/palindrome-partitioning/。
方法一:
采用简单的递归法。
例如对于一个字符串:aad.
- 首先截取第一个字符a,是回文串:
-
- 然后判断第二个字符a,是回文串,
-
-
- 继续判断第三个字符b,是回文串,最后到达结束条件,所以结果添加这个子串集。
-
-
- 判断第二个字符串ab,不是回文串,就不添加。
-
- 然后截取前两个字符串,aa,是回文串:
-
- 然后判断第三个字符b,是回文串, 最后到达结束条件,所以结果添加这个子串集。
-
- 最后判断整个字符串aab,不是回文串,不添加。
class Solution:
def _partition(self, s, index, t, result):
if index == len(s):
result.append(t.copy())
return
for i in range(index+1, len(s)+1):
if s[index:i] == s[index:i][::-1]:
t.append(s[index:i])
self._partition(s, i, t, result)
t.pop() # 注意这里要弹出t的第一个值
def partition(self, s):
"""
:type s: str
:rtype: List[List[str]]
"""
result = list()
if not s:
return result
self._partition(s, 0, list(), result)
return result
方法二:
结合动态规划和深度优先搜索:
首先建立一个表dp[length][length],dp[i][j]为1表示的是s[i,j]是一个回文串,(包含头和尾),这里要注意。
建立了动态规划表就可以根据表的信息深度优先搜索所有的遍历这个表,找到所有可能分割回文子串。
初始条件:
d
p
[
i
]
[
i
]
=
T
r
u
e
dp[i][i] = True
dp[i][i]=True
迭代式为:
d
p
[
i
]
[
i
+
1
]
=
s
[
i
]
=
=
s
[
i
+
1
]
d
p
[
j
]
[
j
+
i
]
=
d
p
[
j
+
1
]
[
j
+
i
−
1
]
  
&
&
  
(
s
[
j
]
=
=
s
[
j
+
i
]
)
dp[i][i+1] = s[i] == s[i+1]\\ dp[j][j+i] = dp[j+1][j+i-1]\; \&\&\; (s[j] == s[j+i])
dp[i][i+1]=s[i]==s[i+1]dp[j][j+i]=dp[j+1][j+i−1]&&(s[j]==s[j+i])
可以发现这个递归式和5.最长回文子串的递归式是完全相同的。可见难点还是写出递归式。
class Solution:
def dfs(self, low, high, s , res,dp, temp = []):
# temp放在函数中作为一个传入的值,就可以不同进行弹出
#操作了,因为这样这个值就不会再不同的递归路径共享了。
if low == high:
res.append(temp)
return
for i in range(low, high):
if dp[low][i]:
self.dfs(i+1,high,s,res,dp,temp+[s[low:i+1]])
def partition(self, s: str) -> List[List[str]]:
length = len(s)
dp = [[0]*length for _ in range(length)]
for i in range(length):
for j in range(length-i):
if s[j] == s[j+i] and(i<2 or dp[j+1][j+i-1]==1):
dp[j][j+i] =1
res = []
self.dfs(0,length,s,res,dp)
return res