代码随想录算法训练营第十六天 | Java |110.平衡二叉树 、 257. 二叉树的所有路径 、404.左叶子之和 、222.完全二叉树的节点个数

110. 平衡二叉树

题目:给定一个二叉树,判断它是否是平衡二叉树

提示:

  • 树中的节点数在范围 [0, 5000] 内
  • -104 <= Node.val <= 104

思路:首先明确平衡二叉树的概念,即二叉树左右子树高度差绝对值不大于1。在判断过程中,当任意一个节点的左右节点差绝对值大于1时,即能证明该二叉树不平衡。用递归法实现,后续遍历记录当前节点左右子树深度差。【我说的比较简略,附上代码随想录的详细解题思路供大家学习】

代码随想录讲解

注意:本题采用后续遍历,是因为需要先计算出当前节点左右子树的高度,最后比较其高度差。

Java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public boolean isBalanced(TreeNode root) {
        return getHeight(root) != -1;
    }

    private int getHeight(TreeNode root){
        if(root == null){
            return 0;
        }

        int leftHeight = getHeight(root.left);
        if(leftHeight == -1){
            return -1;
        }

        int rightHeight = getHeight(root.right);
        if(rightHeight== -1){
            return -1;
        }

        //左右子树高度差大于1,return-1 表示已经不是平衡树
        if(Math.abs(leftHeight-rightHeight)>1){
            return -1;
        }

        return Math.max(leftHeight,rightHeight)+1;
    }
}

  2 257. 二叉树的所有路径

题目:给你一个二叉树的根节点 root ,按 任意顺序 ,返回所有从根节点到叶子节点的路径。叶子节点 是指没有子节点的节点。

提示:

  • 树中节点的数目在范围 [1, 100] 内
  • -100 <= Node.val <= 100

思路:本题要求记录路径,采用前序遍历的方式,便于输出,当遇到叶子节点,收集一个保存的路径。本题一大难点在于路径前序遍历中失效节点的弹出,这里采用回溯的方法去掉这些无效节点。

代码随想录讲解

注意:路径记录中,采用“->”来表明方向,因此在生成新路径记录时,需要考虑到叶子节点即最后一个节点后不需要加“->”。

Java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<String> binaryTreePaths(TreeNode root) {
        List<String> res = new ArrayList<>();   // 保存最终结果
        if(root == null){
            return res;
        }

        List<Integer> paths = new ArrayList<>();    // 作为结果中的路径
        traversal(root,paths,res);
        return res; 

    }

    private void traversal(TreeNode root, List<Integer> paths, List<String> res){
        paths.add(root.val);

        // 遇到叶子节点
        if(root.left == null && root.right == null){
            // 输出
            StringBuilder sb = new StringBuilder();     // 拼接字符串,速度更快
            for(int i = 0; i<paths.size()-1; i++){
                sb.append(paths.get(i)).append("->");  // 路径记录到倒数第二个,防止->加多了
            }
            sb.append(paths.get(paths.size()-1));
            res.add(sb.toString());
            return ;
        }

        // 递归和回溯是同时进行的,要放在同一个花括号里面
        if(root.left != null){
            traversal(root.left,paths,res);
            paths.remove(paths.size()-1);
        }
        if(root.right != null){
            traversal(root.right,paths,res);
            paths.remove(paths.size()-1);
        }
    }
}

404. 左叶子之和

题目: 给定二叉树的根节点 root ,返回所有左叶子之和。

提示:

  • 节点数在 [1, 1000] 范围内
  • -1000 <= Node.val <= 1000

思路:本题需要判断两个问题:是否为叶子节点,是否为左叶子,很明显这么思考就很难做出来了hhh。最好的方式是在叶子的父节点上进行判断,父节点的左孩子是否为空,左孩子的左右节点是否为空,据此来判断是否为左叶子。

 代码随想录讲解

注意:不理解的可以自己画个二叉树把实现过程落实到纸上看的明明白白。

Java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public int sumOfLeftLeaves(TreeNode root) {
        if(root == null){
            return 0;
        }
        
        int leftValue = sumOfLeftLeaves(root.left);
        int rightValue = sumOfLeftLeaves(root.right);

        int mid = 0;
        if(root.left != null && root.left.left == null && root.left.right == null){     // 判断左节点是否为叶子节点
            mid = root.left.val;
        } 

        int sum = mid + leftValue + rightValue;
        return sum;

    }
}

222. 完全二叉树的节点个数

题目: 给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

提示:

  • 树中节点的数目范围是[0, 5 * 104]
  • 0 <= Node.val <= 5 * 104
  • 题目数据保证输入的树是 完全二叉树

思路:最基本的思路就是用递归方法实现遍历,当前节点分别遍历左子树和右子树,然后返回值+1(根节点),即为总的节点个数。还有一种思路,因为提供的是完全二叉树,可以利用完全二叉树的性质来直接计算节点个数。若当前完全二叉树为满二叉树,可根据 节点数=2^树深-1 来计算,如何判断是否为满二叉树,根据根节点分别遍历最左边和最右边的层数来比较,若数值一致,则说明为满二叉树,若不一致,按照递归方法实现。

代码随想录讲解

注意: 判断为满二叉树的条件是根节点遍历最左边和最右边的深度,若一致,证明叶子节点全铺满了且深度一致,故此可以推断。

Java实现

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
// class Solution {
//     public int countNodes(TreeNode root) {
//         if(root == null){
//             return 0;
//         }
//         return countNodes(root.left) + countNodes(root.right) + 1;
//     }
// }
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null){
            return 0;
        }
        TreeNode left = root.left;
        TreeNode right = root.right;
        int leftDepth = 0, rightDepth = 0;
        while(left!=null){
            left = left.left;
            leftDepth++;
        }
        while(right!=null){
            right = right.right;
            rightDepth++;
        }
        if(leftDepth==rightDepth){
            return (2<<leftDepth)-1;
        }
        return countNodes(root.left) + countNodes(root.right) +1;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值