LeetCode 110 平衡二叉树
题目链接:110. 平衡二叉树 - 力扣(Leetcode)
平衡二叉树主要需要判断其所有子树是否都是高度差不大于1,第一次接触时不知道如何确定递归的返回值,后序遍历时既需要知道左右子树的高度,又需要知道左右子树各自是否平衡。讲解中比较巧妙的做法是返回一个固定值(比如高度不会为负数,可以使用-1)作为以该节点为根的子树不平衡的标志,子树平衡时则返回其高度:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def getDepth(self, node):
if not node:
return 0
leftDepth = self.getDepth(node.left)
rightDepth = self.getDepth(node.right)
if leftDepth == -1 or rightDepth == -1:
return -1 # 当有子树不平衡时,整棵树都不平衡
if abs(leftDepth - rightDepth) > 1:
return -1 # 以当前node为根的子树不平衡
else:
return 1 + max(leftDepth, rightDepth) # 平衡时返回node的高度
def isBalanced(self, root: Optional[TreeNode]) -> bool:
if self.getDepth(root) == -1:
return False
else:
return True
代码实现要注意需要先判断左右子树各自是否平衡,而不是先判断左右子树返回值的差值,否则当左右返回值均为-1时容易出错。
LeetCode 257 二叉树所有路径
题目链接:257. 二叉树的所有路径 - 力扣(Leetcode)
涉及到路径,并且是“所有”,典型的递归+回溯,第一次刷题时的写法有些混乱,特别是回溯的位置,并且也是不正确的:
# # Definition for a binary tree node.
# # class TreeNode:
# # def __init__(self, val=0, left=None, right=None):
# # self.val = val
# # self.left = left
# # self.right = right
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
res = []
if not root:
return res
path = []
def dfs(node):
if not node:
return
# 把当前遍历到的节点加入路径
path.append(str(node.val))
path.append('->')
# 依次遍历左子树和右子树
dfs(node.left)
dfs(node.right)
if not node.left and not node.right:
# 遍历到了叶子节点
res.append(''.join(path[:-1]))
# 回溯
path.pop() # pop '->'
path.pop() # pop node.val
return
dfs(root)
return res
二刷重新梳理思路和代码逻辑之后:
# # Definition for a binary tree node.
# # class TreeNode:
# # def __init__(self, val=0, left=None, right=None):
# # self.val = val
# # self.left = left
# # self.right = right
class Solution:
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
if not root:
return []
res, path = [], []
def dfs(node):
if not node:
return
# 把当前遍历到的节点加入路径
path.append(str(node.val) + '->')
if not node.left and not node.right:
# 遍历到了叶子节点
res.append(''.join(path)[:-2])
path.pop() # 别忘了这里也需要回溯
return
# 依次遍历左子树和右子树
dfs(node.left)
dfs(node.right)
path.pop() # pop回溯 node.val + '->'
return
dfs(root)
return res
看了讲解发现,做法一之所以不对是缺少了一次回溯(相当于收集结果以后没有把最近一次加入路径的叶节点回溯掉,它就会出现在其他路径中),做法二提交没问题,因为代码实现的差异,回溯的位置可能与一般做法不太一样。总的来说也算是做了两次回溯。
LeetCode 404 左叶子之和
题目链接:404. 左叶子之和 - 力扣(Leetcode)
题意很明确,只有在左叶子节点处累加节点值,代码实现时感到有点吃力,也不太理解讲解中递归的逻辑:
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumOfLeftLeaves(self, root: TreeNode) -> int:
if not root:
return 0
left_left_leaves_sum = self.sumOfLeftLeaves(root.left) # 左
right_left_leaves_sum = self.sumOfLeftLeaves(root.right) # 右
cur_left_leaf_val = 0
if root.left and not root.left.left and not root.left.right:
cur_left_leaf_val = root.left.val
return cur_left_leaf_val + left_left_leaves_sum + right_left_leaves_sum # 中
今天有点忙,暂时先做到这,周末有时间会来再看看。