題目
給定一個字符串 s,將 s 分割成一些子串,使每個子串都是回文串。
返回 s 所有可能的分割方案。
思考
問題可以分為兩個子問題:1、判斷回文串2、分割數組
判斷回文串
bool isPalindrome_string(string s,int startindex,int endindex)
{for(int i = startindex,j = endindex;i<j;i++,j--){if(s[i] != s[j]) return false;}return true;
}
利用回溯法分割
回溯法分割數組和回溯法求組合的方法類似:
組合問題:選取一個a之后,在bcdef中再去選取第二個,選取b之后在cdef中在選取第三個…。
切割問題:切割一個a之后,在bcdef中再去切割第二段,切割b之后在cdef中在切割第三段…。
回溯的參數與返回值
//全局變量
vector<vector<string>> result;
vector<string> res;
//遞歸函數
void backtracking(string s,int startindex)
回溯的終止條件
當我們的startindex剛好超過了string 的范圍時,說明已經切割完成了,此時將res(各個回文子串)送入result
if(startindex>=s.size())
{result.push_back(res);return;
}
回溯的邏輯
對于每一層來說,有一個startindex,從startindex到i檢查是否是回文串,如果是那么將這個區間的回文字符放入子結果中,并且以這個區間的右邊的一個元素開始,進入下一層的檢查。如果在這個區間的字符不是回文字符串,那么跳過這個區間不進行處理。
需要注意的地方:
1、對于切割過的位置,不能重復切割。
2、substr函數的使用方法
3、單個元素也可以是回文子串,所以子串區間:[startindex,i]
for(int i=startindex;i<s.size();i++)
{//子串區間:[startindex,i]if(isPalindrome_string(s,startindex,i) == true){//substr切割s,第一個參數是起始位置,第二個參數是切割長度string Palindrome_string = s.substr(startindex, i - startindex + 1);res.push_back(Palindrome_string);}else continue;//如果是回文子串,則進入下一層,如果不是,仍在這一層繼續尋找回文串//遞歸,探索下一層,切割過的位置,不能重復切割backtracking(s,i+1); //回溯,撤銷處理結果res.pop_back();
}
代碼
class Solution {
public://全局變量vector<vector<string>> result;vector<string> res;bool isPalindrome_string(string s,int startindex,int endindex){for(int i = startindex,j = endindex;i<j;i++,j--){if(s[i] != s[j]) return false;}return true;}//遞歸函數void backtracking(string s,int startindex){if(startindex>=s.size()){result.push_back(res);return;}for(int i=startindex;i<s.size();i++){//子串區間:[startindex,i]if(isPalindrome_string(s,startindex,i) == true){//substr切割s,第一個參數是起始位置,第二個參數是切割長度string Palindrome_string = s.substr(startindex, i - startindex + 1);res.push_back(Palindrome_string);}else continue;//如果是回文子串,則進入下一層,如果不是,仍在這一層繼續尋找回文串//遞歸,探索下一層,切割過的位置,不能重復切割backtracking(s,i+1); //回溯,撤銷處理結果res.pop_back();}}vector<vector<string>> partition(string s) {result.clear();res.clear();backtracking(s,0);return result;}
};