132 分割回文串 II

2022-05-08 22:09:10 字數 3660 閱讀 9716

給定乙個字串 s,將 s 分割成一些子串,使每個子串都是回文串。

返回符合要求的最少分割次數。

示例:輸入: 「aab」

輸出: 1

解釋: 進行一次分割就可將 s 分割成 [「aa」,「b」] 這樣兩個回文子串。

1.我最開始想到了要兩次dp,先算乙個是否是回文數的dp陣列,再算所求的dp。

但第二個dp陣列我用的二維陣列,然後就變成了o(n^3)時間。因為對於其中每個元素都要從左邊界遍歷到右邊界進行分割,沒有想到可以利用第乙個dp中的資料。

**是對的,自己機器跑了,但ac不了,第26個用例超時:

超時的**!:

1

class

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++:

1

class

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:

1

class

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...