110. 平衡二叉树
- 我在写递归的时候,会希望返回值就是需要的值,因此选了bool作为返回值。但写着写着发现depth也是不可缺少的返回值,因此加上了depth写的递归。但是题解里面只返回一个参数depth,用depth=-1来表示不是平衡二叉树,更简洁。
- 迭代法:好好好复杂。。。思路其实也很简单,就是层次遍历的时候每个节点算一遍左右子树的深度,判断是不是平衡二叉树。每次算深度都要遍历树,重复计算很多的。
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
res, tree_depth = self.depth(root)
return res
def depth(self, root):
# 递归法
# 返回值是bool,左右高度,参数是root节点.需要知道左右高度。
# 终止条件
if not root:
return True, 0
# 一层递归
res1, left_depth = self.depth(root.left)
res2, right_depth = self.depth(root.right)
return res1 and res2 and (abs(left_depth-right_depth) <= 1), max(left_depth, right_depth)+1
257. 二叉树的所有路径
- 没有看题解前自己写的递归。还是之前的思路,需要的东西作为返回值,于是直接将所有路径作为返回值。但是list比较适合增加节点,因此不用str用list存储路径,得到结果后再变为str。
- 递归的时候需要考虑左右节点为空的情况,否则会有重复。这可能是因为空也是终止条件的缘故。按道理空应该不是终止条件,叶子节点才是终止条件。
- 每次递归的时候,是把root加在递归结果的前面,还蛮绕的。
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
if not root:
return []
path_list = self.Paths(root)
# print(path_list)
res = []
for path in path_list:
# print(path)
res.append("->".join(path))
return res
def Paths(self, root):
# 也可以用递归好像
if not root:
return [[]]
if not root.left and not root.right:
return [[str(root.val)]]
left = self.Paths(root.left)
right = self.Paths(root.right)
if not root.left:
return [[str(root.val)]+path for path in right]
if not root.right:
return [[str(root.val)]+path for path in left]
return [[str(root.val)]+path for path in left]+ [[str(root.val)]+path for path in right]
# 不知道直接dfs可不可以
- 相比于我自己的递归,题解的递归看上去还是要舒服一点。result作为参数,也作为最终结果。path是之前经过的路径,也就是每个节点自身的路径。当遍历到叶子节点的时候,才把路径加入到result里面。(有一个默认条件是:一个节点只对应一个路径,这好像也是二叉搜索树成立的基础?)
- 但是回溯这部分的逻辑不是很明白。
- 隐形回溯也不是很明白。。
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
if not root:
return []
result = []
self.traversal(root, [], result)
return result
def traversal(self, cur, path, result):
# cur不可能为空
path.append(cur.val)
if not cur.left and not cur.right:
sPath = "->".join(map(str, path))
result.append(sPath)
if cur.left:
self.traversal(cur.left, path, result)
path.pop() # 回溯?
if cur.right:
self.traversal(cur.right, path, result)
path.pop() # 回溯
隐形回溯1:
def traversal(self, cur: TreeNode, path: List[int], result: List[str]) -> None:
if not cur:
return
path.append(cur.val)
if not cur.left and not cur.right:
result.append('->'.join(map(str, path)))
if cur.left:
self.traversal(cur.left, path[:], result)
if cur.right:
self.traversal(cur.right, path[:], result)
隐形回溯2:
def traversal(self, cur: TreeNode, path: str, result: List[str]) -> None:
path += str(cur.val)
# 若当前节点为leave,直接输出
if not cur.left and not cur.right:
result.append(path)
if cur.left:
# + '->' 是隐藏回溯
self.traversal(cur.left, path + '->', result)
if cur.right:
self.traversal(cur.right, path + '->', result)
404. 左叶子之和
- 自己写了个递归,因为需要判断是不是左,因此加了个tag。不加的话就是再往下推一层,应该也蛮好写的
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
# 递归的话,就是遍历,然后遍历到左叶子就加上去,否在不加?
# 根节点不是叶子
if not root:
return 0
return self.traverse(root, 0)
# 设一个tag,左为1,右为0
def traverse(self, root, tag):
if not root:
return 0
if tag and not root.left and not root.right:
return root.val
left = self.traverse(root.left, 1)
right = self.traverse(root.right, 0)
return left + right