二叉树专题(四)——二叉树遍历及经典习题

文章探讨了二叉树遍历的递归策略,包括自顶向下的应用场景(如LeetCode965和124题),以及自底向上的适用场景(如LeetCode563、687题,涉及路径和计算)。作者强调了根据问题依赖关系选择适当遍历方式的重要性。
摘要由CSDN通过智能技术生成

一、一些对于二叉树遍历的递归写法的体会

对于大部分题而言,二叉树遍历的递归写法可以自顶向下来写,也可以自底向上来写,因为既需要考虑父节点和左右子节点的关系,同时左右子节点也存在依赖关系。

对于必须考虑根结点或父节点,或左右子节点之间无依赖的情况,只能采取自顶向下来写。

对于左右子树之间有依赖关系,或存在无法考虑包含根结点或父节点的情况,只能采取自底向上来写。

在写自底向上方向的递归时,建议从左子树和右子树的方向上考虑,将总问题拆分成两个子问题,无需过多考虑递归过程。

可以将要求取的变量作为全局变量,在执行递归时更新全局变量,递归结束后直接返回全局变量作为答案。

可以将要求取的变量作为递归函数返回值,在执行递归时计算并将结果回传,递归结束后的返回值为答案。

对于二叉树,一般可以从自身节点是否为空或左右子节点是否为空来进行考虑,当从左右子节点方向考虑时,需要先判断左右子节点是否为空,若存在左子结点或右子节点时,再进行递归计算。

二、一些二叉树的经典习题

Leetcode965 单值二叉树

该解法为自顶向下考虑

class Solution {
    public boolean isUnivalTree(TreeNode root) {
        if (root == null) {
            return true;
        }
        if (root.left != null) {
            if (root.val != root.left.val || !isUnivalTree(root.left)) {
                return false;
            }
        }
        if (root.right != null) {
            if (root.val != root.right.val || !isUnivalTree(root.right)) {
                return false;
            }
        }
        return true;
    }
}

 Leetcode563 二叉树的坡度

二叉树的坡度为左子树之和与右子树之和的差的绝对值,与左右子树存在依赖,推荐自底向上来写。

class Solution {
    int ans = 0;

    public int findTilt(TreeNode root) {
        dfs(root);
        return ans;
    }

    public int dfs(TreeNode node) {
        if (node == null) {
            return 0;
        }
        int sumLeft = dfs(node.left);
        int sumRight = dfs(node.right);
        ans += Math.abs(sumLeft - sumRight);
        return sumLeft + sumRight + node.val;
    }
}

Leetcode687 最长同值路径

题目中说该路径可能不经过根结点,所以只能自底向上的方式书写递归。

注意递归函数回传的是该点左右子树分别计算后符合题意的返回的值,所以不应该加上当前节点的值。

class Solution {
    int res;

    public int longestUnivaluePath(TreeNode root) {
        res = 0;
        dfs(root);
        return res;
    }

    public int dfs(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int left = dfs(root.left), right = dfs(root.right);
        int left1 = 0, right1 = 0;
        if (root.left != null && root.left.val == root.val) {
            left1 = left + 1;
        }
        if (root.right != null && root.right.val == root.val) {
            right1 = right + 1;
        }
        res = Math.max(res, left1 + right1);
        return Math.max(left1, right1);
    }
}

Leetcode124 二叉树中的最大路径和

题目中说该路径可能不经过根结点,所以只能自底向上的方式书写递归。

与687题差不多,注意该题需要计算和返回的是路径之和。

注意递归函数回传的是该点左右子树分别计算后符合题意的返回的值,所以不应该加上当前节点的值。

class Solution {
    int maxSum = Integer.MIN_VALUE;

    public int maxPathSum(TreeNode root) {
        maxGain(root);
        return maxSum;
    }

    public int maxGain(TreeNode node) {
        if (node == null) {
            return 0;
        }
        
        // 递归计算左右子节点的最大贡献值
        // 只有在最大贡献值大于 0 时,才会选取对应子节点
        int leftGain = Math.max(maxGain(node.left), 0);
        int rightGain = Math.max(maxGain(node.right), 0);

        // 节点的最大路径和取决于该节点的值与该节点的左右子节点的最大贡献值
        int priceNewpath = node.val + leftGain + rightGain;

        // 更新答案
        maxSum = Math.max(maxSum, priceNewpath);

        // 返回节点的最大贡献值
        return node.val + Math.max(leftGain, rightGain);
    }
}

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值