1. 程式人生 > >[C++]LeetCode: 121 Palindrome Partitioning (分割回文子串 回溯法)

[C++]LeetCode: 121 Palindrome Partitioning (分割回文子串 回溯法)

題目:

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"]
  ]

思路:我們需要將一個字串分割成迴文子串的形式,然後返回所有的分割結果。需要兩個輔助函式,一個是遞迴的DFS,幫助我們分割字串,可以借鑑Restore IP Addresses

的分割思想,我們迴圈所有的分割長度,從1開始直到剩餘子串的長度(注意可以取等號i = s.size()),然後判斷這個子串是否是迴文,可以借鑑Valid Palindrome 中的方法,我們設定兩個座標從頭尾判斷,同時移動,如果有不相等返回false. 如果這個子串是迴文,新增到tmp結果中,將剩餘的字串傳給helper函式繼續遞迴,直到剩餘子串為空時,返回結果。重要的是,我們需要維護現場,將新增進去的子串結果pop_back出來。這樣保證下次選擇不同長度時,沒有重複字元在結果中。

Attention:

1. 迭代終止條件,剩餘子串長度為0.

if(s.size() == 0)
        {
            ret.push_back(tmp);
            return;
        }
2. 每次選擇剩餘子串進行遞迴。遞迴結束後,要維護現場。
int strlen = s.size();
                tmp.push_back(substr);
                partition_helper(s.substr(i, strlen - i), tmp, ret);
                tmp.pop_back();
3. i代表分割子串的長度,不是座標,所以長度可以取字串的長度。注意取等號。
for(int i = 1; i <= s.size(); i++)

複雜度:取決於結果的數量,最壞情況是指數量級的。

AC Code:

class Solution {
public:
    vector<vector<string>> partition(string s) {
        vector<vector<string>> ret;
        if(s.size() == 0) return ret;
        vector<string> tmp;
        partition_helper(s, tmp, ret);
        return ret;
    }

private:
    void partition_helper(string s, vector<string> tmp, vector<vector<string>>& ret)
    {
        if(s.size() == 0)
        {
            ret.push_back(tmp);
            return;
        }
        
        for(int i = 1; i <= s.size(); i++)
        {
            string substr = s.substr(0, i);
            if(isPalindrome(substr))
            {
                int strlen = s.size();
                tmp.push_back(substr);
                partition_helper(s.substr(i, strlen - i), tmp, ret);
                tmp.pop_back();
            }
        }
    }
    
    //假設不含空格等其他字元,只含小寫字母
    bool isPalindrome(string s) 
    {
        int len = s.size();
        if(len == 0 || len == 1) return true;
        int i = 0;
        int j = len - 1;
        
        while(i < j)
        {
            if(s[i++] != s[j--])
            {
                return false;
            }
        }
        return true;
    }
};