[LeetCode] Palindrome Partitioning II

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.


不管最后CUT怎么求,第一步肯定是要求一个数组来表示给定的[i ,j ] 这个范围的子串是否是回文了。
这个也是个DP解法,假设我们 要问  [ i, j ] 是否是回文,条件是  s[i] == s[j] &&  [i+1,j-1] 是回文,对吧~ 
所以我们从长度为1的开始求,然后最后得到的数组 dp [ l ][ i] 就是以 i 打头的长度为l 的这个子串是否是回文,这样查询是O(1)的,创建DP数组是O(n2)的。

得到了DP数组之后我们来看怎么求最小CUTS。
比较直观的DP, 枚举切分点,然后判断左右需要的切分次数加1就好了,这样的算法复杂度是O(n3)的。
一般枚举切分点其实都可以换一个思维,编程枚举上一个切分点,这个跟股票交易是一样的。 
假设  f (i ,j ) 范围的最小切分, 如果  [i ,j ] 是回文,那么不用切分,为0 ,否则我们枚举最近一个切分点 k ,
那么 f (i, j)  = min{  f(i, k)+ 1 } ,是吧,但是切了之后的  [k+1, i] 这一段必须是回文,好在我们已经有DP数组了,这个判断直接就有了。
所以我们从i 从小到大依次计算,最后返回 f(n-1)就是了。
这一步的复杂度是 O(n2)的,
所以最后的复杂度是O(n2)。

class Solution {
public:
    int minCut(string s) {
        // Note: The Solution object is instantiated only once and is reused by each test case.
        
		int n=s.length();
		vector<vector<bool> > dp(n+1,vector<bool>(n,true));
		for(int len=2;len<=n;len++)
		{
			for(int start=0;start<=n-len;start++)
			{
				dp[len][start]=s[start]==s[len+start-1]&&dp[len-2][start+1];
			}
		}

		vector<int> part(n,0);
		for(int i=1;i<n;i++)
		{
			if(dp[i+1][0])
			{
				part[i]=0;
				continue;
			}
			int	cuts=n;
			for(int j=0;j<i;j++)
			{
				if( dp[i-j][j+1] )
				{
					cuts=min(cuts,part[j]);
				}
			}
			part[i]=cuts+1;
		}
		return part[n-1];
	}
};	




你可能感兴趣的:([LeetCode] Palindrome Partitioning II)