6、二叉树和递归

内容来自刘宇波老师玩转算法面试

1、二叉树天然的递归结构

104 - 二叉树的最大深度

public int maxDepth(TreeNode root) {
    if (root == null) return 0;
    return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}

更多问题
111 - 二叉树的最小深度

2、一个简单的二叉树问题引发的血案

226 - 翻转二叉树

public TreeNode invertTree(TreeNode root) {
    if (root == null) return null;

    TreeNode l = invertTree(root.left);
    TreeNode r = invertTree(root.right);

    root.left = r;
    root.right = l;
    return root;
}

更多问题
100 - 相同的树
101 - 对称二叉树
222 - 完全二叉树的节点个数
110 - 平衡二叉树

// 完全二叉树的节点个数
public int countNodes(TreeNode root) {
    if (root == null) return 0;

    int lefDepth = lefDepth(root);
    int rightDepth = rightDepth(root);

    if (lefDepth == rightDepth) return (int) (Math.pow(2, lefDepth) - 1);
    else return countNodes(root.left) + countNodes(root.right) + 1;
}

public int lefDepth(TreeNode node) {
    if (node == null) return 0;
    return lefDepth(node.left) + 1;
}

public int rightDepth(TreeNode node) {
    if (node == null) return 0;
    return rightDepth(node.right) + 1;
}

3、注意递归的终止条件

112 - 路径总和

image

// 错误的代码
public boolean hasPathSum1(TreeNode root, int targetSum) {
    if (root == null) return true;

    return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}

// 正确的代码
public boolean hasPathSum2(TreeNode root, int targetSum) {
    if (root == null) return false;
    if (root.left == null && root.right == null) return targetSum == root.val; // 叶子节点

    return hasPathSum(root.left, targetSum - root.val) || hasPathSum(root.right, targetSum - root.val);
}

更多问题
404 - 左叶子之和

4、定义递归问题

257 - 二叉树的所有路径

public List<String> binaryTreePaths(TreeNode root) {
    List<String> res = new ArrayList<>();
    if (root == null) return res;
    if (root.left == null && root.right == null) {
        res.add("" + root.val);
        return res;
    }

    for (String s : binaryTreePaths(root.left)) res.add(root.val + "->" + s);
    for (String s : binaryTreePaths(root.right)) res.add(root.val + "->" + s);

    return res;
}

更多问题
113 - 路径总和 II
129 - 求根节点到叶节点数字之和

5、稍复杂的递归逻辑

437 - 路径总和 III

image
image

// 在以 root 为根节点的二叉树中, 寻找和为 sum 的路径, 返回路径个数
public static int pathSum(TreeNode root, int sum) {
    if (root == null) return 0;

    int res = findPath(root, sum);   // 包含当前 root 节点, 和为 sum 的路径
    res += pathSum(root.left, sum);  // 不包含当前 root 节点, 和为 sum 的路径
    res += pathSum(root.right, sum); // 不包含当前 root 节点, 和为 sum 的路径

    return res;
}

// 在以 node 为根节点的二叉树中, 寻找包含 node 的和为 sum 的路径, 返回路径个数
private static int findPath(TreeNode node, long sum) {
    if (node == null) return 0;

    int res = 0;
    if (node.val == sum) res++;
    res += findPath(node.left, sum - node.val);
    res += findPath(node.right, sum - node.val);

    return res;
}

6、二分搜索树中的问题

二分搜索树

235 - 二叉搜索树的最近公共祖先

image

// 只要 p 和 q 不在 root 的同侧, 那么 root 就是最近公共祖先
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    if (root == null) return null;

    if (p.val < root.val && q.val < root.val) return lowestCommonAncestor(root.left, p, q);
    if (p.val > root.val && q.val > root.val) return lowestCommonAncestor(root.right, p, q);
    return root;
}

更多问题
98 - 验证二叉搜索树
450 - 删除二叉搜索树中的节点
108 - 将有序数组转换为二叉搜索树
230 - 二叉搜索树中第 K 小的元素
236 - 二叉树的最近公共祖先

posted @ 2023-05-16 19:49  lidongdongdong~  阅读(7)  评论(0编辑  收藏  举报