給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。
返回符合要求的最少分割次數。
示例:輸入: 「aab」
輸出: 1
解釋: 進行一次分割就可將 s 分割成 [「aa」,「b」] 這樣兩個回文子串。
1.我最開始想到了要兩次dp,先算乙個是否是回文數的dp陣列,再算所求的dp。
但第二個dp陣列我用的二維陣列,然後就變成了o(n^3)時間。因為對於其中每個元素都要從左邊界遍歷到右邊界進行分割,沒有想到可以利用第乙個dp中的資料。
**是對的,自己機器跑了,但ac不了,第26個用例超時:
超時的**!:
1class
solution:
2def mincut(self, s: str) ->int:3#
先算乙個dp陣列記錄是否是回文數4#
dp[i][j]記錄s[i,j]閉區間是否是回文數
5 l=len(s)6if
nots:
7return
08 dp=[[0 for i in range(l)] for j in
range(l)]
9for i in
range(l):
10 dp[i][i]=1 #
乙個元素的一定是回文數,遞推起始條件
11for i in range(l-1):
12if s[i]==s[i+1]:
13 dp[i][i+1]=1 #
兩個相鄰元素的若值相同,也為回文數
14for step in range(2,l):
15 i=0
16while i+step17 j=i+step #
j為右邊界,考察s[i,j]是否是回文數18#
矩陣的右上半部,滿足i<=j才有意義
19 dp[i][j]=int(dp[i+1][j-1] and s[i]==s[j])20#
當前字串為回文數的條件:兩邊界截掉是回文數
21 i+=122#
回文數dp陣列建立好,考慮對於s[i,j]字串的最少分割次數f(i,j),23#
若當前字串為回文數即dp[i][j]==1則分割次數f(i,j)為0,不用割,24#
否則可能的切割位置為i+1到j-1,假設切割位置為k(i25
#還需要知道f(i,k),f(k+1,j),故還需要乙個求最少分割次數的dp陣列
26 dp2=[[float('
inf') for i in range(l)] for j in
range(l)]
27for i in
range(l):
28 dp2[i][i]=0 #
單個字串不用割,其他元素初始化為無窮大
29for step in range(1,l): #
對[i,i+step]閉區間考察,i取0時,0+step應該小於l
30 i=0
31while i+step32if dp[i][i+step]==1: #
若s[i,i+step]已是回文
33 dp2[i][i+step]=0
34else:35
#若s[i,i+step]不是回文,則一定要切,下面開始切
36 cur_min=float('
inf')37
for cut in range(i,i+step):38#
找割數最小的割法
39 cur_min=min(cur_min,dp2[i][cut]+dp2[cut+1][i+step]+1)
40 dp2[i][i+step]=cur_min
41 i+=142#
print(dp)43#
print(dp2)
44return dp2[0][l-1]
2.正確**:
第乙個dp陣列一樣,必須是二維的。第二個dp陣列一維的,dp2[i]表示從i開始到末尾的字串的最小分割數,對於每個dp[i],在i+1到n-1找分割點k就完事了,i到k為回文串通過第乙個dp陣列查詢,o(1),剩下的k到n-1是之前算好的,所以第二個dp陣列要從右往左算,因為右邊界不動。總體o(n^2)複雜度。
c++:
1class
solution
8for(int i=0;i]?true:false);}
9 //下往上,左往右算dp
10for(int i=n-3;i>=0;--i)14}
15 vectordp(n,inf);//dp[i]表示s截止到i最小分割次數(inf表示沒法分割)
16for(int i=0;ii)
21for(int cut=1;cut<=i;++cut)25}
26}27return dp[n-1];28}
29 };
python:
1class
solution:
2def mincut(self, s: str) ->int:
3 l=len(s) #
先算乙個dp陣列記錄是否是回文,dp[i][j]記錄s[i,j]閉區間是否是回文數4if
notl:
5return
06 dp=[[0 for i in range(l)] for j in
range(l)]
7for i in range(l-1,-1,-1): #
從下往上,從右往左算
8for j in range(l-1,i-1,-1):
9if s[i]==s[j]:
10 dp[i][j]=1 if j-i<2 else dp[i+1][j-1]
11 dp2=[float('
inf') for i in range(l)] #
dp2[i]表示從i開始到末尾字串的最小分割數
12for i in range(l-1,-1,-1):
13if dp[i][l-1]: #
當前字串是回文數
14 dp2[i]=0
15else
:16 _min=float('
inf')17
for cut in range(i,l-1): #
不同割點位置
18if dp[i][cut]==1:
19 _min=min(dp2[cut+1]+1,_min)
20 dp2[i]=_min
21print
(dp2)
22return dp2[0]
132 分割回文串 II
給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。返回符合要求的最少分割次數。示例 輸入 aab 輸出 1 解釋 進行一次分割就可將 s 分割成 aa b 這樣兩個回文子串。解法一 public class solution else return dp 0 解法二 如果從分割字串的角...
leetcode132 分割回文串II
給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。返回符合要求的最少分割次數。示例 輸入 aab 輸出 1 解釋 進行一次分割就可將 s 分割成 aa b 這樣兩個回文子串。01揹包 給定num個物品,每種物品都有自己的重量 wi 和價值 vi,且都為整數,在限定的總重量weight內...
DP LeetCode132 分割回文串 II
給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。返回符合要求的最少分割次數。輸入 aab 輸出 1 解釋 進行一次分割就可將 s 分割成 aa b 這樣兩個回文子串。class solution object def mincut self,s type s str rtype in...