【LeetCode】palindrome-partitioning i&ii

題幹

palindrome-partitioning i

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s =”aab”,
Return

  [
    ["aa","b"],
    ["a","a","b"]
  ]

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”,
Return1since the palindrome partitioning[“aa”,”b”]could be produced using 1 cut.

兩個迴文字符串的題,第一個要把字串都是迴文的情況都存儲下來,第二個是求得到字串都是迴文需要對原字符串分割多少次。

解題思路

第一個題

對字符串進行遍歷,每當找到一個迴文的子串之後,繼續找剩下的子串中的會問子串,利用遞歸直到找完整個字符串即可。動態規劃也可解。

第二個題

運用動態規劃的想法,主要步驟分爲3步。

1.子串substr(0,i+1)的最小回文分割爲dp[i],並且初始化,如果substr(0,i+1) 爲迴文子串,那麼dp[i]=0,即不需要分割,否則爲i,即分割i 次

  1. 任意大於1的i,子串substr(j,i+1),即遍歷i之前所有子串,是迴文子串,dp[i]=min(dp[i],dp[j-1]+1),即再分割一次。

  2. 如果子串substr(j,i+1)不是迴文,dp[i]=min(dp[i],dp[j-1]+i-j+1)

    上述構成寫成代碼即可。

參考代碼

問題一:

class Solution {
public:
    vector<vector<string>>res;//結果的每組子串存儲
    vector<string> tmp;//當前子串
    bool isPalindrome (string s)//是否爲迴文的判斷
    {
        if (s.size()<=0) return false;
        int start=0,end=s.size()-1;
        while(start<=end)
        {
            if(s[start]==s[end])
            {
                start++;
                end--;
            }
            else return false;
        }
        return true;
    }
    void dfs(string s,int pos)//子串遍歷
    {
        if (pos>=s.size())//遞歸退出條件,原字符串全部遍歷之後退出遞歸
        {
            res.push_back(tmp);
            return;
        }

        for(int i=0;i<=s.size()-pos;i++)
        {
            if (isPalindrome(s.substr(pos,i)))
            {
                tmp.push_back(s.substr(pos,i));//將回文子串存到結果中
                dfs(s,pos+i);//從當前位置繼續後面的遍歷
                tmp.pop_back();
            }
        }
    }
    vector<vector<string>> partition(string s)
    {
        dfs(s,0);
        return res;
    }
};

問題二:

class Solution {
public:
    bool isPalindrome (string s)//迴文判斷
    {
        if (s.size()<=0) return false;
        int start=0,end=s.size()-1;
        while(start<=end)
        {
            if(s[start]==s[end])
            {
                start++;
                end--;
            }
            else return false;
        }
        return true;
    }
    int minCut(string s)
    {
        int *dp=new int [s.length()];
        int min;
        for(int i=0;i<s.length();i++)
        {
            dp[i]=(isPalindrome(s.substr(0,i+1)))?0:i;//步驟1:初始化dp[i]
            if (dp[i]==0)//當dp[i]爲0的時候必爲min,故直接下一次循環
                continue;
            for(int j=1;j<=i;j++)
            {
                if (isPalindrome(s.substr(j,i-j+1)))//步驟2
                    dp[i]=(dp[i]<dp[j-1]+1)?dp[i]:dp[j-1]+1;
                else
                    dp[i]=(dp[i]<dp[j-1]+i-j+1)?dp[i]:dp[j-1]+i-j+1;//步驟3
            }

        }
        return dp[s.length()-1];//返回dp最後的結果
    }
};

方法討論

兩個題都可以用動態規劃解決,字符串子串的這種問題主要用類似於深度遍歷的方法,每次從當前位置向後遍歷,適合用遞歸。

易錯點

遞歸跳出條件

遞歸跳出是遍歷結束之後進行跳出。

邊界條件

1.迴文判斷的時候循環結束條件是要在前後兩個指針順序start<=end來結束,<或者=單獨條件都不可以。

2.第2題中的s.substr(j,i-j+1)迴文的判斷對於子串長度爲i-j+1。這個容易錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章