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

解题思路:

动态规划。用d[i]表示前i个字符需要的最大切分数目。则d[i+1]的最大值不会超过d[i]+1。若第i+1个字符与前面第j个字符开始构成回文,则d[i+1]=min(d[i]+1, d[j-1]+1)。注意这里要验证每个j的情况。下面是相关代码:

class Solution {
public:
    int minCut(string s) {
        int len=s.length();
        if(len==0||len==1){
            return 0;
        }
        int* d=new int[len];
        d[0]=0;
        for(int i=1; i<len; i++){
            d[i]=d[i-1]+1;
            for(int j=0; j<i; j++){
                int l=j, r=i;
                while(l<r){            //验证j到r是否为回文
                    if(s[l]==s[r]){
                        l++;
                        r--;
                    }else{
                        break;
                    }
                }
                if(l>=r){           //表示j到i是回文
                    if(j==0){
                        d[i]=0;
                    }else{
                        d[i]=min(d[i], d[j-1]+1);
                    }
                }
            }
        }
        
        int result=d[len-1];
        delete[] d;
        return result;
    }
    
    int min(int a, int b){
        return a>b?b:a;
    }
};

提交上去,发生超时错误。这个算法的时间复杂度为O(n3)。能否更快呢?原来在检查j到i是否为回文的过程中,我们做了很多重复运算。假如我们知道s[j+1, i-1]是回文,若s[j]==s[i],那么s[j, i]也是回文。因此我们可以用一个二维数组来记录这个特征。下面是改后的代码。

class Solution {
public:
    int minCut(string s) {
        int len=s.length();
        if(len==0||len==1){
            return 0;
        }
        
        bool** bIsPalin=new bool*[len];     //二维数组,表示i到j是否是回文
        for(int i=0; i<len; i++){
            bIsPalin[i] = new bool[len];
            bIsPalin[i][i] = true;          //自身到自身是回文
        }
        
        for(int i=0; i<len; i++){
            for(int j=0; j<i; j++){
                if(i==j+1){
                    if(s[i]==s[j]){
                        bIsPalin[j][i]=true;
                    }else{
                        bIsPalin[j][i]=false;
                    }
                }else{
                    bIsPalin[j][i]=s[i]==s[j]&&bIsPalin[j+1][i-1];
                }
            }
        }
        
        int* d=new int[len];
        d[0]=0;
        
        for(int i=1; i<len; i++){
            d[i]=d[i-1]+1;          //上限值
            for(int j=0; j<i; j++){
                if(bIsPalin[j][i]){
                    if(j==0){
                        d[i]=0;
                    }else{
                        d[i]=min(d[i], d[j-1]+1);
                    }
                    //break;
                }
            }
        }
        
        int result=d[len-1];
        //释放空间
        delete[] d;
        for(int i=0; i<len; i++){
            delete[] bIsPalin[i];
        }
        delete[] bIsPalin;
        
        return result;
    }
    
    int min(int a, int b){
        return a>b?b:a;
    }
};

更改后的代码的时间复杂度为O(n2)。

0 条评论

    发表评论

    电子邮件地址不会被公开。 必填项已用 * 标注