leetcode之Palindrome Partitioning II

来源:互联网 发布:gradle mac 环境变量 编辑:程序博客网 时间:2024/05/02 00:54

题目大意:

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.

意思就是:

给定字符串s,求得最小的划分数,使得划分的字符串都是回文串。

做题思路:

1,可以借鉴Palindrome Partitioning的做题结果,把所有的情况都存下来。最后求得最大数。但是这样不是time limited就是memory limited。

2,做题的过程中,我还采用了一种错误的做题思路,即贪心算法——从第一个字符开始,求的最长的回文,然后从该回文的下一个字符开始继续求。最后证明结果是错的。、

3,这道题目太难,自己想不出。最后网上找了思路——动态规划。

a,改良前的动态规划。

   类似矩阵连乘的动归思路。
dp[i][j]=min(dp[i][k]+dp[k+1][j]+1), i<=k<j.
dp[i][j]表示从第i个字符到第j个字符,最小的切分数。但是用这个方程的时间是O(n^3),简化dp[i][j]为dp[i],表示从0到i的minCut.

b,改良后的动态规划。

dp[i]=min(dp[k]+1,       dp[k]+i-k), 0<=k<i.

 (s[k+1, i]是回文串)   (s[k+1, i]不是回文串)

c,注意:判断字符串是否是回文,也不能用Palindrome Partitioning的方法了,因为动态规划很多子问题。这些字问题中判断字符串是否是回文的时候,有很多字符串是重复的。所以有必要采用动态规划的方式——递归加记忆化。详见代码。

代码如下:

class Solution {public:int minCut(string s){string::size_type str_length = s.length();if(str_length ==0 || str_length == 1){return 0;}int i;min.resize(str_length+1);min[0] = 0;vector<int> hehe;for(i=0;i<str_length;i++){hehe.push_back(-1);}for(i=0;i<str_length;i++){track.push_back(hehe);}int tmp = 0, result, k;for(i=1;i<str_length+1;i++){//string nn = s.substr(0,i);if(ifpalindrome(s,0,i-1)){min[i] = 0;}else{    result = i;    for(k=0;k<i;k++){    //string mm = s.substr(k,i-k);    if(ifpalindrome(s,k,i-1)){    tmp = min[k] + 1;    }    else{    tmp = min[k] + i - k;    }    if(tmp < result){    result = tmp;    }     }    min[i] = result;}}return min[str_length];}bool ifpalindrome(string& s,int i,int j){if(i>j){return false;}if(track[i][j] != -1){return track[i][j];}if(i == j){return track[i][j]=1;}if(s[i] != s[j]){return false;}else{if(j-i == 1){return track[i][j]=1;}else{return track[i][j] = ifpalindrome(s,i+1,j-1);}}}private:vector<int> min;vector< vector<int> > track;};


0 0