Day17 二叉树part04
110.平衡二叉树
本题的思路:检查左右子树的高度,如果检查过程中就发现了高度差大于1的情况直接返回-1,计算高度采用后序遍历
递归逻辑:
- 明确递归函数的参数和返回值:**参数:**当前传入节点。 返回值:以当前传入节点为根节点的树的高度。如果当前传入节点为根节点的二叉树已经不是二叉平衡树了,还返回高度的话就没有意义了。所以如果已经不是二叉平衡树了,可以返回-1 来标记已经不符合平衡树的规则了。
- 终止条件:遇到空节点则返回高度为0
- 明确单层递归的逻辑:如果左右子树已经得到标记高度为-1则直接返回-1,代表已经不是平衡二叉树了;如果都不是则计算一下两者的差值,对中间的根节点进行更新(伪代码)
int leftHeight = getHeight(node->left); // 左
if (leftHeight == -1) return -1;
int rightHeight = getHeight(node->right); // 右
if (rightHeight == -1) return -1;
int result;
if (abs(leftHeight - rightHeight) > 1) { // 中
result = -1;
} else {
result = 1 + max(leftHeight, rightHeight); // 以当前节点为根节点的树的最大高度
}
return result;
代码python:
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
result = self.get_height(root)
if result == -1: return False
else: return True
def get_height(self, root: TreeNode) ->int:
if not root:
return 0
left_height = self.get_height(root.left)
if left_height == -1: return -1
right_height = self.get_height(root.right)
if right_height == -1: return -1
if abs(left_height-right_height)>1:
return -1
else:
return 1+max(left_height, right_height)
257. 二叉树的所有路径
题意:给定一个二叉树,返回所有从根节点到叶子节点的路径。
采用的是前序遍历:因为由父节点指向子节点生成一条路径
为什么需要回溯:因为我们要把路径记录下来,需要回溯来回退一个路径再进入另一个路径。
- **递归参数和返回值:**当前根节点cur,当前路径path,结果路径result
- **终止条件:**之前都是如果根节点为None的情况终止,但是本题中是想找到叶子节点返回,也就是循环到none的上一层,即判断cur→left == NULL并且cur→right == NULL的时候是叶子节点;
- 为什么不想None终止呢,这涉及到下面单层递归的逻辑,每次都是先将目前的节点cur放到路径里,然后判断是不是叶子节点,如果最后的结果是None那么相当于多放了一个None进来
- **单层递归逻辑:因为是前序遍历(中左右)所以先处理中的逻辑,中间节点就是我们要记录路径上的节点,先放进path中。**如果已经是叶子节点了就不继续递归了。递归完,要做回溯啊,因为path 不能一直加入节点,它还要删节点,然后才能加入新的节点。
- 回溯和递归是一一对应的:左侧是正确的,右侧为错误的
if (cur->left) {
traversal(cur->left, path, result);
path.pop_back(); // 回溯
}
if (cur->right) {
traversal(cur->right, path, result);
path.pop_back(); // 回溯
}
if (cur->left) {
traversal(cur->left, path, result);
}
if (cur->right) {
traversal(cur->right, path, result);
}
path.pop_back();
python代码:
# 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 traversal(self, cur, path, result):
path.append(cur.val)
if not cur.left and not cur.right:
res_path = '->'.join(map(str, path))
result.append(res_path)
return
if cur.left:
self.traversal(cur.left, path, result)
path.pop()
if cur.right:
self.traversal(cur.right, path, result)
path.pop()
def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
result = []
path = []
if not root:
return result
self.traversal(root, path, result)
return result
404.左叶子之和
首先要注意是判断左叶子,不是二叉树左侧节点,所以不要上来想着层序遍历。
因为题目中其实没有说清楚左叶子究竟是什么节点,那么我来给出左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点
思路:
- 后序遍历:逐层向上每个子树的左叶子之和
- 判断的时候是cur→left不为空且cur→left的left和right为空
class Solution:
def sumOfLeftLeaves(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
if root.left is None and root.right is None: #叶子节点的子树是空,所以左叶子之和也是空
return 0
left_sum = self.sumOfLeftLeaves(root.left)
if root.left and not root.left.left and not root.left.right: #处理叶子节点,在父节点处相加
left_sum = root.left.val
right_sum = self.sumOfLeftLeaves(root.right)
return left_sum+right_sum