給你乙個字串 s,請你將 s 分割成一些子串,使每個子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正著讀和反著讀都一樣的字串。
示例 1:
輸入:s = "aab"輸出:[["a","a","b"],["aa","b"]]
示例 2:
輸入:s = "a"
輸出:[["a"]]
1 <= s.length <= 16回溯法s 僅由小寫英文本母組成
看到題目要求「所有可能的結果」,而不是「結果的個數」,一般情況下,我們就知道需要暴力搜尋所有的可行解了,可以用「回溯法」。
「回溯法」實際上乙個類似列舉的搜尋嘗試過程,主要是在搜尋嘗試過程中尋找問題的解,當發現已不滿足求解條件時,就「回溯」返回,嘗試別的路徑。
回溯法是一種演算法思想,而遞迴是一種程式設計方法,回溯法可以用遞迴來實現。
回溯法的整體思路是:搜尋每一條路,每次回溯是對具體的一條路徑而言的。對當前搜尋路徑下的的未探索區域進行搜尋,則可能有兩種情況:
上面說的未搜尋區域是指搜尋某條路徑時的未搜尋區域,並不是全域性的未搜尋區域。
backtrack 的含義是:未探索區域中到達結束條件的所有可能路徑,path 變數是儲存的是一條路徑,res 變數儲存的是所有搜尋到的路徑。所以當「未探索區域滿足結束條件」時,需要把 path 放到結果 res 中。
path.pop() 是啥意思呢?它是程式設計實現上的乙個要求,即我們從始至終只用了乙個變數 path,所以當對 path 增加乙個選擇並 backtrack 之後,需要清除當前的選擇,防止影響其他路徑的搜尋。
本題需要我們把字串分成一系列的回文子串,按照模板,我們的思路應該是這樣的:
未探索區域:剩餘的未搜尋的字串 s;
結束條件:s 為空;
未探索區域當前可能的選擇:每次選擇可以選取 s 的 1 - length 個字元,cur=s[0...i]cur = s[0...i]cur=s[0...i];
當前選擇符合要求:cur 是回文字串 ispalindrome(cur)ispalindrome(cur)ispalindrome(cur);
新的未探索區域:s 去除掉 cur 的剩餘字串,s[i+1...n]s[i + 1...n]s[i+1...n]。
回溯模板**
res =
path =
def backtrack(未探索區域, res, path):
if 未探索區域滿足結束條件:
res.add(path) # 深度拷貝
return
for 選擇 in 未探索區域當前可能的選擇:
if 當前選擇符合要求:
path.add(當前選擇)
backtrack(新的未探索區域, res, path)
path.pop()
下面分享了兩種解法,分別對應了每次複製 path 和 不複製 path 的解法。這裡是乙個容易出錯的細節。
c++ 解法使用的是和我上面分析的一樣的所有路徑共享 path 的實現,需要對 path 進行 push 和 pop 操作,當把 path 放入 res 中時,需要深度拷貝,而 vector 的 push_back() 函式,本身就是深度拷貝。
class solution(object):
def partition(self, s):
self.ispalindrome = lambda s : s == s[::-1]
res =
self.backtrack(s, res, )
return res
def backtrack(self, s, res, path):
if not s:
return
for i in range(1, len(s) + 1): #注意起始和結束位置
if self.ispalindrome(s[:i]):
self.backtrack(s[i:], res, path + [s[:i]])
class solution );
return res;
}void backtrack(string s, vector>& res, vectorpath)
for (int i = 1; i <= s.size(); i++) }}
bool ispalindrome(string s)
return true;
}};
時間複雜度:o(n∗2n)o(n * 2 ^ n)o(n∗2n),因為總共有 o(2n)o(2^n)o(2n) 種分割方法,每次分割都要判斷是否回文需要 o(n)o(n)o(n) 的時間複雜度。
空間複雜度:o(2n)o(2 ^ n)o(2n),返回結果最多有 o(2n)o(2 ^ n)o(2n) 種劃分方法。
回溯法模板
void run 當前狀態 for int i 算符最小值 i 算符最大值 i 這只是乙個大致的輪廓,需要根據試題要求,做適當的調整。例如,對非最優性問題,可略去當前狀態是否為最佳目標狀態和擴充套件出的子狀態是否滿足最優性要求的判斷,若是求最長路徑,可略去邊界條件的判斷,等等,但是在使用回溯法解題時...
leetcode 回溯法 模板
dfs 模板.param in input 輸入資料指標 param out path 當前路徑,也是中間結果 param out result 存放最終結果 param inout cur or gap 標記當前位置或距離目標的距離 return 路徑長度,如果是求路徑本身,則不需要返回長度 vo...
python 回溯法 記錄
一直不是太理解回溯法,這幾天集中學習了一下,記錄如下。回溯法有 通用的解題法 之稱。1.定義 2.基本思想 3.一般步驟 4.約束函式 5.限界函式 6.子集樹模板 遍歷子集樹,時間複雜度 o 2 n 如果解的長度是不固定的,那麼解和元素順序無關,即可以從中選擇0個或多個。例如 子集,迷宮,如果解的...