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

意思就是:

给定字符串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;
};


你可能感兴趣的:(LeetCode,C++,算法)