LeetCode:Palindrome Partitioning
題目如下:(把一個字符串劃分成幾個回文子串,枚舉所有可能的劃分)
Given a string? s , partition? s ?such that every substring of the partition is a palindrome.
Return all possible palindrome partitioning of? s .
For example, given?
s
?=?
"aab"
,
Return
[ ["aa","b"], ["a","a","b"] ]
?
分析 :首先對字符串的所有子串判斷是否是回文,設f[i][j] = true表示以i為起點,長度為j的子串是回文,等于false表示不是回文,那么求f[i][j]的動態規劃方程如下:
-
當j = 1,f[i][j] = true;
-
當j = 2,f[i][j] = (s[i]==s[i+1]),其中s是輸入字符串
-
當j > 2, f[i][j] = f[i+1][j-2] && (s[i] == s[i+j-1])(即判斷s[m..n]是否是回文時:只要s[m+1...n-1]是回文并且s[m] = s[n],那么它就是回文,否則不是回文)
這一題也可以不用動態規劃來求f,可以用普通的判斷回文的方式判斷每個子串是否為回文。 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 本文地址
求得f后,根據 f 可以構建一棵樹,可以通過DFS來枚舉所有的分割方式,代碼如下:
1 class Solution { 2 public : 3 vector<vector< string >> partition( string s) { 4 // IMPORTANT: Please reset any member data you declared, as 5 // the same Solution instance will be reused for each test case. 6 vector< vector< string > > res; 7 int len = s.length(); 8 if (len == 0 ) return res; 9 // f[i][j] = true表示以i為起點,長度為j的子串是回文 10 bool **f = new bool * [len]; 11 for ( int i = 0 ; i < len; i++ ) 12 { 13 f[i] = new bool [len+ 1 ]; 14 for ( int j = 0 ; j < len+ 1 ; j++ ) 15 f[i][j] = 0 ; 16 f[i][ 1 ] = true ; 17 } 18 for ( int k = 2 ; k <= len; k++ ) 19 { 20 for ( int i = 0 ; i <= len-k; i++ ) 21 { 22 if (k == 2 )f[i][ 2 ] = (s[i] == s[i+ 1 ]); 23 else f[i][k] = f[i+ 1 ][k- 2 ] && (s[i] == s[i+k- 1 ]); 24 } 25 } 26 vector< string > tmp; 27 DFSRecur(s, f, 0 , res, tmp); 28 for ( int i = 0 ; i < len; i++ ) 29 delete [](f[i]); 30 delete []f; 31 return res; 32 } 33 34 void DFSRecur( const string &s, bool **f, int i, 35 vector< vector< string > > &res, vector< string > & tmp) 36 { // i為遍歷的起點 37 int len = s.length(); 38 if (i >= len){res.push_back(tmp); return ;} 39 for ( int k = 1 ; k <= len - i; k++ ) 40 if (f[i][k] == true ) 41 { 42 tmp.push_back(s.substr(i, k)); 43 DFSRecur(s, f, i+ k, res, tmp); 44 tmp.pop_back(); 45 } 46 47 } 48 };
LeetCdoe:Palindrome Partitioning II
題目如下:(在上一題的基礎上,找出最小劃分次數)
Given a string? s , partition? s ?such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of? s .
For example, given?
s
?=?
"aab"
,
Return?
1
?since the palindrome partitioning?
["aa","b"]
?could be produced using 1 cut. ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
本文地址
算法1 :在上一題的基礎上,我們很容易想到的是在DFS時,求得樹的最小深度即可(遍歷時可以根據當前求得的深度進行剪枝),但是可能是遞歸層數太多,大數據時運行超時,也貼上代碼:

算法2 :設f[i][j]是i為起點,長度為j的子串的最小分割次數,f[i][j] = 0時,該子串是回文,f的動態規劃方程是:
f[i][j] = min{f[i][k] + f[i+k][j-k] +1} ,其中 1<= k <j
這里f充當了兩個角色,一是記錄子串是否是回文,二是記錄子串的最小分割次數,可以結合上一題的動態規劃方程,算法復雜度是O(n^3), 還是大數據超時,代碼如下:

算法3 :同上一題,用f來記錄子串是否是回文,另外優化最小分割次數的動態規劃方程如下,mins[i] 表示子串s[0...i]的最小分割次數:
- 如果s[0...i]是回文,mins[i] = 0
- 如果s[0...i]不是回文,mins[i] = min{mins[k] +1 (s[k+1...i]是回文) ?或 ?mins[k] + i-k ?(s[k+1...i]不是回文)} ,其中0<= k < i
代碼如下,大數據順利通過,結果Accept: ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?? 本文地址
1 class Solution { 2 public : 3 int minCut( string s) { 4 // IMPORTANT: Please reset any member data you declared, as 5 // the same Solution instance will be reused for each test case. 6 int len = s.length(); 7 if (len <= 1 ) return 0 ; 8 // f[i][j] = true表示以i為起點,長度為j的子串是回文 9 bool **f = new bool * [len]; 10 for ( int i = 0 ; i < len; i++ ) 11 { 12 f[i] = new bool [len+ 1 ]; 13 for ( int j = 0 ; j < len+ 1 ; j++ ) 14 f[i][j] = false ; 15 f[i][ 1 ] = true ; 16 } 17 int mins[len]; // mins[i]表示s[0...i]的最小分割次數 18 mins[ 0 ] = 0 ; 19 for ( int k = 2 ; k <= len; k++ ) 20 { 21 for ( int i = 0 ; i <= len-k; i++ ) 22 { 23 if (k == 2 )f[i][ 2 ] = (s[i] == s[i+ 1 ]); 24 else f[i][k] = f[i+ 1 ][k- 2 ] && (s[i] == s[i+k- 1 ]); 25 } 26 if (f[ 0 ][k] == true ){mins[k- 1 ] = 0 ; continue ;} 27 mins[k- 1 ] = len - 1 ; 28 for ( int i = 0 ; i < k- 1 ; i++ ) 29 { 30 int tmp; 31 if (f[i+ 1 ][k-i- 1 ] == true )tmp = mins[i]+ 1 ; 32 else tmp = mins[i]+k-i- 1 ; 33 if (mins[k- 1 ] > tmp)mins[k- 1 ] = tmp; 34 } 35 } 36 for ( int i = 0 ; i < len; i++ ) 37 delete [](f[i]); 38 delete []f; 39 return mins[len- 1 ]; 40 } 41 42 };
?【版權聲明】轉載請注明出處: http://www.cnblogs.com/TenosDoIt/p/3421283.html
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
