1. 程式人生 > >演算法作業第十週(leetcode)——132.palindrome-partitioning-ii

演算法作業第十週(leetcode)——132.palindrome-partitioning-ii

其實已經不是特別想做動態規劃的題了,但是還是抽到了一道動態規劃的題。下面給出題目描述:

這題的大意是給一個字串,要經過最少多少次分割才能把字串分成迴文串組成的字串。

其實這題動態規劃的部分並不是特別難的部分。很容易就可以想到用cut[i]來表示前i個字元所能分成的迴文串的最小個數。然後用一個數組p[i][j]來表示[i,j)之間的子串是不是迴文串,然後就可實現cut[i]到cut[j]之間的狀態轉移。

我個人覺得難點主要在怎麼在o(n^2)時間內實現迴文串的判斷。如果直接遍歷,那肯定是o(n^3)。一開始想到棧,但是迴文串可能有奇數個字元,不能一一對應。後來看了一下網上發現,迴文串去掉兩邊相同的字元還是迴文串。利用這個性質,我們可以實現一個簡單的遞迴: 

int p[2005][2005];
int cut[2005];
class Solution {
public:
    int isParlindrome(string& s, int i,int j)
    {
        if(i>=j-1)
            return 1;
        if(p[i][j]!=-1)
            return p[i][j];
        if(s[i]!=s[j-1])
            return 0;
        p[i][j] = isParlindrome(s, i+1, j-1);
        return p[i][j];
    }

    int minCut(string s) {
        int i,j;
        memset(p, -1, sizeof(p));
        memset(cut, -1, sizeof(cut));
        for(i=0;i<s.size();i++)
        {
            if(isParlindrome(s,0,i+1))
                cut[i] = 1;
            for(j=0;j<i;j++)
            {
                if(isParlindrome(s,j+1,i+1))
                {
                    if(cut[i]!=-1)
                        cut[i] = min(cut[i],cut[j]+1);
                    else
                        cut[i] = cut[j] + 1;
                }
            }
        }
        return cut[s.size()-1]-1;
    }

};
​

這裡懶得寫vector,直接開了一波陣列然後memset。。。。。所以很慢。。。(個人感覺是這個原因,沒實驗過)

其實這個還可以用迴圈實現,不過我感覺要搞清陣列依賴的關係比較複雜,相對難想。我個人實現了一個迴圈版本:

int p[2005][2005];
int cut[2005];
class Solution {
public:
    int minCut(string s) {
        int i,j;
        memset(p, -1, sizeof(p));
        memset(cut, -1, sizeof(cut));
        for(i=0;i<s.size();i++)
        {
            if(s[0]==s[i]&&(p[1][i]==1||i<=1))
            {
                p[0][i+1] = 1;
                cut[i] = 1;
            }
            for(j=0;j<i;j++)
            {
                if(s[j+1]==s[i]&&(p[j+2][i]==1||j>=i-2))
                {
                    p[j+1][i+1] = 1;
                    if(cut[i]!=-1)
                        cut[i] = min(cut[i],cut[j]+1);
                    else
                        cut[i] = cut[j] + 1;
                }
            }
        }
        return cut[s.size()-1]-1;
    }

};

         快了一點,如果想要再快就改成vector寫法好了: