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

简介: 代码随想录刷题|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;
    }
}


相关文章
|
1天前
|
算法 Unix 测试技术
力扣经典150题第五十二题:简化路径
力扣经典150题第五十二题:简化路径
9 0
|
18天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-2
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
18天前
|
算法 C++
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题-1
【数据结构与算法】:关于时间复杂度与空间复杂度的计算(C/C++篇)——含Leetcode刷题
|
18天前
|
算法
二刷力扣--二叉树(3)
二刷力扣--二叉树(3)
|
18天前
二刷力扣--二叉树(2)
二刷力扣--二叉树(2)
|
18天前
二刷力扣--二叉树(1)基础、遍历
二刷力扣--二叉树(1)基础、遍历
|
19天前
【LeetCode刷题】前缀和解决问题:742.寻找数组的中心下标、238.除自身以外数组的乘积
【LeetCode刷题】前缀和解决问题:742.寻找数组的中心下标、238.除自身以外数组的乘积
|
19天前
【LeetCode刷题】二分查找:寻找旋转排序数组中的最小值、点名
【LeetCode刷题】二分查找:寻找旋转排序数组中的最小值、点名
|
19天前
|
索引
【LeetCode刷题】二分查找:山脉数组的峰顶索引、寻找峰值
【LeetCode刷题】二分查找:山脉数组的峰顶索引、寻找峰值
|
19天前
【LeetCode刷题】专题三:二分查找模板
【LeetCode刷题】专题三:二分查找模板
【LeetCode刷题】专题三:二分查找模板