摸鱼两天,良心开始疼痛,今天恢复。
二叉树部分差两个part抽空补上,直接开回溯~
LC 77 组合
class Solution:
def backTracking(self , n , k , id):
if len(self.path) == k:
self.res.append(self.path[:])
return self.res
for i in range(id , n + 1):
self.path.append(i)
self.backTracking(n , k , i + 1)
self.path.pop()
return self.res
def combine(self, n: int, k: int) -> List[List[int]]:
self.path = []
self.res = []
return self.backTracking(n , k ,1)
听过一遍后来写,还是踩了坑:
第一,self.res.append(self.path[:])中的path,不能直接写self.path,因为列表是可变的,直接写得到的不是你想得到的,而是最后的样子。
第二,务必要让i取得到 n ,否则就会漏解。
再次感受下递归的思路:
其实递归的次数,就是for循环的层数,我们不能手动写50个for循环,但是计算机递归50次是可以做到的。取数的逻辑是,第一次取1,第二次取2,取到2发现长度等于n,就把2pop掉,再取3,以此类推。
LC 216 组合总和Ⅲ
跟上一题思路一致
class Solution:
def backTracking(self , n , k , start_index):
if len(self.path) == k and sum(self.path) == n:
self.res.append(self.path[:])
return self.res
for i in range(start_index , 10):
self.path.append(i)
self.backTracking( n, k , i + 1)
self.path.pop()
return self.res
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
self.path = []
self.res = []
return self.backTracking(n , k , 1)
LC 17 电话号码的字母组合
class Solution:
def back_track(self , digits , index = 0):
if index == len(digits):
self.res.append(self.path)
return
digit = int(digits[index])
letters = self.words[digit]
for i in range(len(letters)):
self.path += letters[i]
self.back_track(digits , index + 1 )
self.path = self.path[0:-1]
return self.res
def letterCombinations(self, digits: str) -> List[str]:
self.words = [
0 , 0 ,'abc' ,'def' ,'ghi' , 'jkl' ,'mno',
'pqrs' , 'tuv' , 'wxyz'
]
self.path = ''
self.res = []
if not digits:
return []
return self.back_track(digits)
对比这几题,对如何用index去控制递归处理的起始位置;递归何时结束有了更深得感受。
前两题的index是从哪里开始枚举,第三题的index指向输入的字符串的第几个位置。对于第三题的终止条件,若index = 1 就停止的话,就没有递归处理到第二个字符 , 因此需要让index = digits.size再终止。
tips:动手画下树形结构,有助于理解