diff --git "a/problems/0131.\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262.md" "b/problems/0131.\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262.md" index 811044da89..3d52146bec 100644 --- "a/problems/0131.\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262.md" +++ "b/problems/0131.\345\210\206\345\211\262\345\233\236\346\226\207\344\270\262.md" @@ -290,100 +290,88 @@ class Solution { ``` ## Python -```python -# 版本一 +**回溯+正反序判断回文串** +```python3 class Solution: + def __init__(self): + self.paths = [] + self.path = [] + def partition(self, s: str) -> List[List[str]]: - res = [] - path = [] #放已经回文的子串 - def backtrack(s,startIndex): - if startIndex >= len(s): #如果起始位置已经大于s的大小,说明已经找到了一组分割方案了 - return res.append(path[:]) - for i in range(startIndex,len(s)): - p = s[startIndex:i+1] #获取[startIndex,i+1]在s中的子串 - if p == p[::-1]: path.append(p) #是回文子串 - else: continue #不是回文,跳过 - backtrack(s,i+1) #寻找i+1为起始位置的子串 - path.pop() #回溯过程,弹出本次已经填在path的子串 - backtrack(s,0) - return res - + ''' + 递归用于纵向遍历 + for循环用于横向遍历 + 当切割线迭代至字符串末尾,说明找到一种方法 + 类似组合问题,为了不重复切割同一位置,需要start_index来做标记下一轮递归的起始位置(切割线) + ''' + self.path.clear() + self.paths.clear() + self.backtracking(s, 0) + return self.paths + + def backtracking(self, s: str, start_index: int) -> None: + # Base Case + if start_index >= len(s): + self.paths.append(self.path[:]) + return + + # 单层递归逻辑 + for i in range(start_index, len(s)): + # 此次比其他组合题目多了一步判断: + # 判断被截取的这一段子串([start_index, i])是否为回文串 + temp = s[start_index:i+1] + if temp == temp[::-1]: # 若反序和正序相同,意味着这是回文串 + self.path.append(temp) + self.backtracking(s, i+1) # 递归纵向遍历:从下一处进行切割,判断其余是否仍为回文串 + self.path.pop() + else: + continue ``` -```python -# 版本二 +**回溯+函数判断回文串** +```python3 class Solution: - def partition(self, s: str) -> List[List[str]]: - res = [] - path = [] #放已经回文的子串 - # 双指针法判断是否是回文串 - def isPalindrome(s): - n = len(s) - i, j = 0, n - 1 - while i < j: - if s[i] != s[j]:return False - i += 1 - j -= 1 - return True - - def backtrack(s, startIndex): - if startIndex >= len(s): # 如果起始位置已经大于s的大小,说明已经找到了一组分割方案了 - res.append(path[:]) - return - for i in range(startIndex, len(s)): - p = s[startIndex:i+1] # 获取[startIndex,i+1]在s中的子串 - if isPalindrome(p): # 是回文子串 - path.append(p) - else: continue #不是回文,跳过 - backtrack(s, i + 1) - path.pop() #回溯过程,弹出本次已经填在path的子串 - backtrack(s, 0) - return res -``` -## Go - -注意切片(go切片是披着值类型外衣的引用类型) + def __init__(self): + self.paths = [] + self.path = [] -```go -func partition(s string) [][]string { - var tmpString []string//切割字符串集合 - var res [][]string//结果集合 - backTracking(s,tmpString,0,&res) - return res -} -func backTracking(s string,tmpString []string,startIndex int,res *[][]string){ - if startIndex==len(s){//到达字符串末尾了 - //进行一次切片拷贝,怕之后的操作影响tmpString切片内的值 - t := make([]string, len(tmpString)) - copy(t, tmpString) - *res=append(*res,t) - } - for i:=startIndex;i List[List[str]]: + ''' + 递归用于纵向遍历 + for循环用于横向遍历 + 当切割线迭代至字符串末尾,说明找到一种方法 + 类似组合问题,为了不重复切割同一位置,需要start_index来做标记下一轮递归的起始位置(切割线) + ''' + self.path.clear() + self.paths.clear() + self.backtracking(s, 0) + return self.paths + + def backtracking(self, s: str, start_index: int) -> None: + # Base Case + if start_index >= len(s): + self.paths.append(self.path[:]) + return + + # 单层递归逻辑 + for i in range(start_index, len(s)): + # 此次比其他组合题目多了一步判断: + # 判断被截取的这一段子串([start_index, i])是否为回文串 + if self.is_palindrome(s, start_index, i): + self.path.append(s[start_index:i+1]) + self.backtracking(s, i+1) # 递归纵向遍历:从下一处进行切割,判断其余是否仍为回文串 + self.path.pop() # 回溯 + else: + continue + + def is_palindrome(self, s: str, start: int, end: int) -> bool: + i: int = start + j: int = end + while i < j: + if s[i] != s[j]: + return False + i += 1 + j -= 1 + return True ``` ## javaScript