給你乙個字串 s,請你將 s 分割成一些子串,使每個子串都是回文。
返回符合要求的 最少分割次數 。
示例 1:
輸入:s =
"aab"
輸出:1
解釋:只需一次分割就可將 s 分割成 [
"aa","b"
] 這樣兩個回文子串。
示例 2:
輸入:s =
"a"輸出:0
示例 3:
輸入:s =
"ab"
輸出:1
1 <= s.length <= 2000
s 僅由小寫英文本母組成
方法一:動態規劃
思路與演算法
設 f[i]f[i] 表示字串的字首 s[0..i]s[0..i] 的最少分割次數。要想得出 f[i]f[i] 的值,我們可以考慮列舉 s[0..i]s[0..i] 分割出的最後乙個回文串,這樣我們就可以寫出狀態轉移方程:
f[i]
= 0≤jmin +1,其中 s[j+1..i] 是乙個回文串
即我們列舉最後乙個回文串的起始位置 j+1j+1,保證 s[j+1..i]s[j+1..i] 是乙個回文串,那麼 f[i]f[i] 就可以從 f[j]f[j] 轉移而來,附加 11 次額外的分割次數。
注意到上面的狀態轉移方程中,我們還少考慮了一種情況,即 s[0..i]s[0..i] 本身就是乙個回文串。此時其不需要進行任何分割,即:
f[i]
= 0f[i]
=0那麼我們如何知道 s[j+1..i]s[j+1..i] 或者 s[0..i]s[0..i] 是否為回文串呢?我們可以使用與「131. 分割回文串的官方題解」中相同的預處理方法,將字串 ss 的每個子串是否為回文串預先計算出來,即:
g(i,j)
=設 g(i, j)g(i,j) 表示 s[i..j]s[i..j] 是否為回文串,那麼有狀態轉移方程:
其中 ∧ 表示邏輯與運算,即 s[i..j]s[i..j] 為回文串,當且僅當其為空串(i>ji>j),其長度為 11(i=ji=j),或者首尾字元相同且 s[i+1..j-1]s[i+1..j−1] 為回文串。
這樣一來,我們只需要 o(1)o(1) 的時間就可以判斷任意 s[i..j]s[i..j] 是否為回文串了。通過動態規劃計算出所有的 ff 值之後,最終的答案即為 f[n-1]f[n−1],其中 nn 是字串 ss 的長度。
**
class
solution
} vector<
int>
f(n, int_max)
;for
(int i =
0; i < n;
++i)
else}}
}return f[n -1]
;}};
複雜度分析
時間複雜度:o(n^2)其中 n 是字串 s 的長度。預處理計算 g 和動態規劃計算 ff 的時間複雜度均為 o(n^2)。
空間複雜度:o(n^2),陣列 g 需要使用 o(n^2)的空間,陣列 f 需要使用 o(n^2)的空間。
今天也是cv的一天。
每日刷題 分割回文串II
給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。返回符合要求的最少分割次數。示例 輸入 aab 輸出 1 解釋 進行一次分割就可將 s 分割成 aa b 這樣兩個回文子串。解法一 沿用分割會文串 的方法,將所有可能的結果列舉出來,然後選擇長度最小的即可。親測,超時。解法二 動態規劃。...
力扣每日一題 131 分割回文串
解題思路 解題 解題感悟 難度 中等 題目 給你乙個字串 s,請你將 s 分割成一些子串,使每個子串都是 回文串 返回 s 所有可能的分割方案。回文串 是正著讀和反著讀都一樣的字串。輸入 s aab 輸出 a a b aa b 輸入 s a 輸出 a 力扣 leetcode 鏈結 首先,回文串是從前...
力扣131 分割回文串
題目 給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。返回 s 所有可能的分割方案。示例 輸入 aab 輸出 aa b a a b 分析 有點向之前求所有子串問題,採用dp動態規劃演算法,只是多加上了判斷是否為回文串,在 aab 一例中可以依次分析如下分割是否滿足回文串特性 a a ...