5
思路:動態規劃
可變參數兩個,分別是行和列,所以建立二維dp表,dp[i][j]
表示i
位置到j
位置是否爲迴文串,那麼可以看出對角線都爲1,對角線以下都不用填,只要填上半張表格。
在判斷i
位置到j
位置是否爲迴文串時,如果使用暴力法會超時,那麼可以採用中心擴展法,如圖所示。
想判斷i
位置到j
位置是否爲迴文串,只要滿足判斷s[i] == s[j]
且dp[i+1][j-1] == 1
,那麼就爲迴文子串,即dp[i][j] = 1
,但注意當i到j距離小於2時,需要進行特殊情況判斷,此時只要s[i] == s[j]
,那麼直接dp[i][j] = 1
一般情況下的遞推公式爲:
由於首先知道了 i + 1
行 纔會知道i
行 ,所以我們只需從下往上要倒着遍歷填表就行了。
過程中利用max_len記錄最大長度並更新
class Solution:
def longestPalindrome(self, s: str) -> str:
if not s:
return ''
n = len(s)
dp =[[0]*n for _ in range(n)]
max_len = float('-inf')
res = ''
for i in range(n-1,-1,-1): #從後往前推
for j in range(i,n):
if s[i] == s[j] and (j - i + 1 <= 2 or dp[i+1][j-1] == 1): #向外擴展
# if s[i:j+1] == s[i:j+1][::-1]: #超時
dp[i][j] = 1
if dp[i][j] == 1 and j - i + 1 > max_len:
max_len = j - i + 1
res = s[i:j+1]
return res
131
思路一
回溯法
class Solution:
def partition(self, s: str) -> List[List[str]]:
if not s:
return []
res = []
def backtrack(s, tmp):
if not s:
res.append(tmp)
for i in range(1, len(s) + 1):
if s[:i] == s[:i][::-1]:
backtrack(s[i:], tmp + [s[:i]])
backtrack(s, [])
return res
思路二
動態規劃法
132
動態規劃
min_split【i】表示到位置的最少分裂次數
class Solution:
def minCut(self, s: str) -> int:
n = len(s)
dp = [[0] * n for _ in range(n)]
min_split = list(range(n))
for i in range(n):
for j in range(i+1):
if s[i] == s[j] and (i - j + 1 <= 2 or dp[j+1][i-1] == 1): #i-j判斷條件要放到dp表判斷條件前面,否則報錯
dp[j][i] = 1
if j == 0:
min_split[i] = 0
else:
min_split[i] = min(min_split[i], min_split[j-1] + 1)
return min_split[-1]