代码随想录刷题|LeetCode 110.平衡二叉树 257.二叉树的所有路径 404.左叶子之和

110.平衡二叉树

题目链接:力扣

思路

        这一道题目算是求数的最大高度的升级版,求树的最大高度采用的是后序遍历

        先左记录、再右记录、再中处理

        那么判断一棵树是不是平衡二叉树我们不仅需要记录它的最大高度,还要判断子树是不是一棵平衡二叉树

        如果不是平衡二叉树,它的最大高度就没有记录的必要了,但是需要对此做出标记

平衡二叉树

递归法

        求树的高度是使用后序遍历

        这道题目不太好写的部分是递归函数“中”的部分不好写

        因为以前在对节点遍历之后,都是处理一件事就可以了,但是这次不仅要记录这个节点的最大高度返回给父节点,还要判断自己是不是一个平衡二叉树

        所以在处理节点的过程中,如果这个节点树是二平衡二叉树,我们就记录这棵树的最大高度,返回给上一层,如果不是平衡二叉树,那就给最大高度赋值-1,返回给上一层

class Solution {
    public boolean isBalanced(TreeNode root) {

        return getHight(root) == -1 ? false : true;

    }

    public int getHight(TreeNode root) {
         
        if (root == null) {
            return 0;
        }

        // 左
        // 记录树的最大高度
        int leftHight = getHight(root.left); 
        // 判断树是否是平衡二叉树
        if (leftHight == -1) {
            return -1;
        }
        
        // 右
        // 记录数的最大高度
        int rightHight = getHight(root.right);
        if (rightHight == -1) {
            return -1;
        }

        // 中
        int result;
        // 判断该树是否是平衡二叉树
        if (Math.abs(rightHight - leftHight) > 1) {
            result = -1;
        } else {
            result = 1 + Math.max(rightHight,leftHight);
        }

        return result;
    }
}

迭代法

这道题目使用迭代法太复杂了,二刷再看

257.二叉树的所有路径

题目链接:力扣

思路

        题目的要求是记录二叉树中的每一条路径,这种情况下我们就要使用前序遍历对二叉树进行处理了,中 左 右 的顺序,这样才方便父节点指向孩子节点,找到对应的路径
        但是每记录一条路径之后,就遍历到了最下面的叶子节点,怎么才能开始从头走第二条道路呢,这就涉及到了回溯的思想,简单来说,就是回退

        再许多情况下,回溯算法相当于穷举搜索的巧妙实现

        类似的题目:112 113

二叉树的所有路径

递归法

        第一步:递归函数的函数参数以及返回值
                我们需要传入根节点,要查看的二叉树;
                需要记录每一条路径的path
                需要存放的结果集result

        第二步:确认递归的终止条件
                这道题的终止条件是找到叶子节点才算终止

        第三步:单层结构的处理
                回溯与递归是一一对应的,有一个递归就要有一个回溯,所以回溯要和递归永远在一起,写在一个花括号之内

        暂时对回溯算法有了初步了解,回溯算法比较难理解的就是递归中的每次回溯,其实调用的递归函数还有自己的回溯,进去是啥,出了递归只是比进去的多了一个节点,所以除掉最后一个就可以了。剩下的在递归里面已经去除干净了

class Solution {
    public List<String> binaryTreePaths(TreeNode root) {

        // 用于保存最后的所有路径
        List<String> result = new ArrayList<>();

        if (root == null) {
            return result;
        }

        // 用于保存每条路径上的节点
        List<Integer> nodes = new ArrayList<>();
        // 调用收集函数
        traversal(root,nodes,result);
        return result;

    }

    // 递归函数
    public void traversal(TreeNode root,List<Integer> nodes,List<String> result) {

        // 中 
        // 如果这个节点是叶子节点,要确保这个节点可以添加到路径中,这是根据终止条件来的
        nodes.add(root.val);

        // 终止条件
        if (root.left == null && root.right == null) {
            // 说明你这条路径走到头了 nodes也将这条路径上的所有元素都添加上去了
            // 这条路径已经成了,那就将这条路径转换成符合要求的格式
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < nodes.size () - 1; i++) { // 长度-1是因为最后一个节点不添加->
                sb.append(nodes.get(i) + "->");
            }
            sb.append(nodes.get(nodes.size () - 1));
            // 将这条路径转换成字符串之后,再添加到结果集中
            result.add(sb.toString());
            return;
        }


        if (root.left != null) {
            traversal(root.left,nodes,result); // 这条语句执行完成之后,说这条路径从这个左节点开始已经记录完成了
            nodes.remove(nodes.size() - 1); // 回溯
        }

        if (root.right != null) {
            traversal(root.right,nodes,result);
            nodes.remove(nodes.size() - 1); // 回溯
        }
    }
}

迭代法

        暂时搁置这种方法的学习,后面再学

404.左叶子之和

题目链接:力扣

思路

        这道题是你找到左叶子,左叶子无法在自身节点上面判断自己是不是左叶子,必须借助节点的父节点来判断其左孩子是不是左叶子

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

        这道题的关键就是要知道怎么筛选出左叶子节点,并对其进行处理

if (node.left != null && node.left.left == null && node.left.right == null) {
    这个才是左叶子
}

左叶子之和

递归法

        因为我们是要统计根节点的左右子树的左叶子数之和,所以采用后序遍历,收集左右的左叶子数之和,然后再对两边的和进行处理

class Solution {
    public int sumOfLeftLeaves(TreeNode root) {

        if (root == null) {
            return 0;
        }
        if (root.left == null && root.right == null) {
            return 0;
        }

        // 左
        int leftNum = sumOfLeftLeaves(root.left);
        
        // 右
        int rightNum = 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 +leftNum + rightNum;

        return sum;     

    }
}

迭代法

        迭代法是比较好理解的,但需要注意的是,就是正常的层序遍历,只是在层序遍历的时候,对符合左叶子的节点进行收割

class Solution {
    public int sumOfLeftLeaves(TreeNode root) {

        // 采用层序遍历
        Deque<TreeNode> deque = new LinkedList<>();

        // 先将根节点入队
        deque.offer(root);

        int sum = 0;
        while (!deque.isEmpty()) {
            int len = deque.size();           
            for (int i = 0; i < len; i++) {
                TreeNode node = deque.poll();
                // 添加左子节点
                if (node.left != null) {
                    deque.offer(node.left);
                }  
                // 添加右子节点
                if (node.right != null) {
                    deque.offer(node.right);
                }
                // 整个程序中,只有出现左叶子的时候,对左叶子的结果进行收割
                if (node.left != null && node.left.left == null && node.left.right == null) {
                    sum = sum + node.left.val;
                }
                             
            }
        }
        return sum;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值