二叉树部分: 110. 平衡二叉树,257. 二叉树的所有路径,404. 左叶子之和

代码随想录算法训练营第15天 | 二叉树部分: 110. 平衡二叉树,257. 二叉树的所有路径,404. 左叶子之和

110. 平衡二叉树

给定一个二叉树,判断它是否是高度平衡的二叉树。本题中,一棵高度平衡二叉树定义为:一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1 。

思路:左右子树在是平衡二叉树的前提下,两者的高度差的绝对值小于等于1
返回值 参数: 返回值为高度差 参数为二叉树
终止条件:节点为空
单层循环:首先考虑左右子树的平衡性 计算左子树的高度,右子树的高度,然后进行判断,需要几个计算高度的函数
思路是对的,虽然写的代码有点长确实是先要保证左子树和右子树的平衡性,再去比较整个二叉树的平衡性,这边当时在犹豫

public boolean isBalanced(TreeNode root) {
      if(root==null){
          return true;
      }
      //左右子树的平衡
      if(!isBalanced(root.left)){
          return false;
      }
      if(!isBalanced(root.right)){
          return false;
      }
      int leftL=getHeight(root.left);
      int rightL=getHeight(root.right);
      //整体的平衡
      if(Math.abs(leftL-rightL)<=1){
          return true;
      }
      return false;
    }
//求树高度的函数
    public int getHeight(TreeNode root){
        if(root==null){
            return 0;
        }
        return Math.max(getHeight(root.left),getHeight(root.right))+1;
    }

257. 二叉树的所有路径

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

思路: 这边涉及到路径的问题,所以递归的参数中就需要携带之前走过的路径,不然最后的结果就只能是当前走过的一个节点而已,这边是着重需要考虑的问题
返回值 参数:返回一个String类型的集合,参数:二叉树,集合
终止条件:节点为空
单层循环:如果节点的左孩子节点不为空的话,加入路径,如果孩子节点不是叶子节点的话,继续往下,否则然后返回节点,如果右孩子不为空的话,加入路径,同样的思路,就是有一个回溯的概念,如果遇到了叶子节点,加入路径之后,需要回溯,同样,当左节点执行完了之后,回溯,然后执行右节点
写不出来,我好迷,List中的元素是String类型,怎么添加元素呢,直接加??,怎么往回走???
答案
返回值 参数: 无返回值 参数:二叉树 路径(这个没想到) 结果集
终止条件:遇到叶子节点即表示路径到头了
单层循环:遍历左子树,回溯,遍历右子树,回溯
当运行到根节点的数据,遍历加入转换为String( 前期通过StringBuilder添加)
在这里插入图片描述

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) {
            //paths.add(root.val);
            // 输出
            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) {
            //paths.add(root.val);
            traversal(root.left, paths, res);
            paths.remove(paths.size() - 1);// 回溯
        }
        if (root.right != null) {
            //paths.add(root.val);//如果直接放在里面的话,可能会存在树的根节点被添加多次的情况
            traversal(root.right, paths, res);
            paths.remove(paths.size() - 1);// 回溯
        }
    }

404. 左叶子之和

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

思路:必须是叶子节点,必须是某个树的左节点
返回值 参数: 二叉树 变量(表示之前的左叶子和)
终止条件:遇到左叶子节点
单层循环:遍历左右子树

这样的思路不是对的,下面的代码在判断了一个左叶子节点之后就返回,是不对的

int count=0;
    public int sumOfLeftLeaves(TreeNode root) {
       if(root==null){
           return 0;
       }
       count=sunOF(root,count);
       return count;
    }
    public int sunOF(TreeNode node, int sum){
        if(node.left!=null && node.left.left==null && node.left.right==null){
            sum +=node.left.val;
            return sum;
        }
        int lef=sunOF(node.left,sum);
        int rig=sunOF(node.right,sum);
        return lef+rig;
    }

//这样的话,总是会出现某左叶子节点的重复添加

 public int sumOfLeftLeaves(TreeNode root) {
       if(root==null){
           return 0;
       }
       int count=0;
       count=sunOF(root,count);
       return count;
    }
    public int sunOF(TreeNode node, int sum){
        if(node.right!=null){
            sum+=sunOF(node.right,sum);
        }

        if(node.left!=null){
            if(node.left.left==null && node.left.right==null){
                sum +=node.left.val;
            }else{
                sum+=sunOF(node.left,sum);
            }

        }
        return sum;
    }

答案:对于左叶子节点的判断是对的,但是递归写的有问题,分析了一下,大概率是我类比路径那题,把每次递归都要加上上一次的左叶子节点,就像路径一样,其实有些节点出现多次,不需要携带左叶子节点的值,左子树中左叶子节点的值+右子树中的左叶子的值+根节点的左孩子是左叶子节点的情况=左叶子节点和

public int sumOfLeftLeaves(TreeNode root) {
       if (root == null) return 0;
        int leftValue = sumOfLeftLeaves(root.left);    // 左
        int rightValue = sumOfLeftLeaves(root.right);  // 右
                                                       
        int midValue = 0;
        if (root.left != null && root.left.left == null && root.left.right == null) { 
            midValue = root.left.val;
        }
        int sum = midValue + leftValue + rightValue;  // 中
        return sum;
    }

总结:路径之和以及左叶子节点的和感觉递归想的不太明白

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值