训练营1007|二叉树(平衡二叉树|所有路径|左叶子之和)day17

本文介绍了平衡二叉树的定义与两种递归算法实现:自顶向下与自底向上。同时探讨了二叉树的所有路径求解及左叶子之和的计算方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

110.平衡二叉树

* 257.二叉树的所有路径

404.左叶子之和


110.平衡二叉树

 平衡二叉树:左右子树的高度差不超过1.

左右子树的高度差不超过1并且也是平衡子树所以构成最后的平衡二叉树

一开始debug没有通过的版本是将高度差不超过1直接return true,然后最后return左右子树是否是平衡子树,这边错误的原因是,如果高度差不超过1走if逻辑的话,可以走最后是否是平衡子树逻辑的就是高度差会超过1的时候。两者之间并非是否则的非此即彼的关系,而是相与

 平衡二叉树:左右子树的高度差不超过1.&&左右子树也是平衡二叉树

 自顶向下的递归:height会重复计算(前序遍历),时间复杂度O(n^2)

class Solution {
    /**
     * 判断是否为平衡二叉树
     *
     * @param root
     * @return
     */
    public boolean isBalanced(TreeNode root) {
        if (root == null) {
            return true;
        }
        int leftlen = getLength(root.left);
        int rightlen = getLength(root.right);
//        if (Math.abs(leftlen - rightlen) <= 1) {
//            return true;
//        }
        return Math.abs(leftlen - rightlen) <= 1&&isBalanced(root.left) && isBalanced(root.right);
    }

    /**
     * 获取二叉树的高度----->最大深度
     *
     * @param root
     * @return
     */
    public int getLength(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return 1 + Math.max(getLength(root.left), getLength(root.right));
    }
}

自底向上的递归:避免了重复计算height,(后序遍历)   时间复杂度:O(n)

自底向上递归的做法类似于后序遍历,对于当前遍历到的节点,先递归地判断其左右子树是否平衡,再判断以当前节点为根的子树是否平衡。如果一棵子树是平衡的,则返回其高度(高度一定是非负整数),否则返回 -1−1。如果存在一棵子树不平衡,则整个二叉树一定不平衡。

 注意:短路或的优化,先判断左子树是不是平衡的,要是左子树不是平衡的也没必要去判断右子树是否平衡

class Solution {
    /**
     * 判断是否为平衡二叉树---->自底向上
     *
     * @param root
     * @return
     */
    public boolean isBalanced(TreeNode root) {
        return getLength(root) >= 0;
    }

    /**
     * 获取高度---->自底向上完全是平衡二叉树,最后可以获得树的高度,但是如果有一个结点不是,直接断掉
     *
     * @param root
     * @return
     */
    public int getLength(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftLength = getLength(root.left);
        int rightLength = getLength(root.right);
        if (leftLength == -1 || rightLength == -1 || Math.abs(leftLength - rightLength) > 1) {
            return -1;
        }
        return 1 + Math.max(leftLength, rightLength);
    }
}

* 257.二叉树的所有路径

递归形式返回二叉树中的所有路径,采用前序遍历,需要利用到回溯。

class Solution {
    /**
     * 二叉树的所有路径---->以list方式返回(递归)
     *
     * @param root
     * @return
     */
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> ans = new ArrayList<>();
        if (root == null) {
            return ans;
        }
        List<Integer> paths = new ArrayList<>();
        travesal(root, paths, ans);
        return ans;
    }

    /**
     * 递归
     */
    public void travesal(TreeNode root, List<Integer> paths, List<String> ans) {
        paths.add(root.val);
        //是叶子结点
        if (root.left == null && root.right == null) {
            //加入结果集,比如 1->3->7->9
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < paths.size() - 1; i++) {
                sb.append(paths.get(i));
                sb.append("->");
            }
            sb.append(paths.get(paths.size() - 1));
            ans.add(sb.toString());
        }
        if (root.left != null) {
            travesal(root.left, paths, ans);
            paths.remove(paths.size() - 1);//回溯
        }
        if (root.right != null) {
            travesal(root.right, paths, ans);
            paths.remove(paths.size() - 1);
        }
    }
}

注重递归运行的顺序

404.左叶子之和

返回二叉树的所有左叶子之和,左叶子首先是叶子结点,再是父节点的左孩子

节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点

所以判断当前节点是不是左叶子是无法判断的,必须要通过节点的父节点来判断其左孩子是不是左叶子。

递归的遍历顺序为后序遍历(左右中),是因为要通过递归函数的返回值来累加求取左叶子数值之和。

class Solution {
    /**
     * 求解二叉树的左子树之和
     *
     * @param root
     * @return
     */
    public int sumOfLeftLeaves(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int leftLeaf = sumOfLeftLeaves(root.left);
        int rightLeaf = sumOfLeftLeaves(root.right);

        int temp = 0;
        if (root.left != null && root.left.left == null && root.left.right == null) {//找到左叶子
            temp = root.left.val;
        }
        return temp + leftLeaf + rightLeaf;
    }
}

注意leftLeaf和rightLeaf的位置,以及进行递归的方法。

2022.11.23补

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值