力扣爆刷第141天之二叉树十连刷(翻转、对称、深度、平衡、路径)

力扣爆刷第141天之二叉树十连刷(翻转、对称、深度、平衡、路径)

文章目录

      • 力扣爆刷第141天之二叉树十连刷(翻转、对称、深度、平衡、路径)
      • [一、226. 翻转二叉树](#一、226. 翻转二叉树)
      • [二、101. 对称二叉树](#二、101. 对称二叉树)
      • [三、104. 二叉树的最大深度](#三、104. 二叉树的最大深度)
      • [四、111. 二叉树的最小深度](#四、111. 二叉树的最小深度)
      • [五、222. 完全二叉树的节点个数](#五、222. 完全二叉树的节点个数)
      • [六、110. 平衡二叉树](#六、110. 平衡二叉树)
      • [七、257. 二叉树的所有路径](#七、257. 二叉树的所有路径)
      • [八、404. 左叶子之和](#八、404. 左叶子之和)
      • [九、513. 找树左下角的值](#九、513. 找树左下角的值)
      • [十、112. 路径总和](#十、112. 路径总和)

一、226. 翻转二叉树

题目链接:https://leetcode.cn/problems/invert-binary-tree/description/

思路:直接前序遍历,然后在遍历的过程中交换左右子节点。

java 复制代码
class Solution {
    public TreeNode invertTree(TreeNode root) {
        traverse(root);
        return root;
    }
    void traverse(TreeNode root) {
        if(root == null) return ;
        TreeNode t = root.left;
        root.left = root.right;
        root.right = t;
        traverse(root.left);
        traverse(root.right);
    }

}

二、101. 对称二叉树

题目链接:https://leetcode.cn/problems/symmetric-tree/description/

思路:将一个棵二叉树当做两颗二叉树来遍历,也就是在递归的函数参数中携带左右两颗子树,然后进行比较。

java 复制代码
class Solution {
    public boolean isSymmetric(TreeNode root) {
        return traverse(root.left, root.right);
    }

    boolean traverse(TreeNode node1, TreeNode node2) {
        if(node1 == null && node2 == null) return true;
        if(node1 == null || node2 == null) return false;
        if(node1.val != node2.val) return false;
        return traverse(node1.left, node2.right) && traverse(node1.right, node2.left);
    }
    
}

三、104. 二叉树的最大深度

题目链接:https://leetcode.cn/problems/maximum-depth-of-binary-tree/description/

思路:后序遍历,返回左右子树的最大值即可,然后每返回一层就加1,即可得到最大深度。

java 复制代码
class Solution {
    public int maxDepth(TreeNode root) {
        if(root == null) return 0;
        int left = maxDepth(root.left);
        int right = maxDepth(root.right);
        return Math.max(left, right) + 1;
    }
}

四、111. 二叉树的最小深度

题目链接:https://leetcode.cn/problems/minimum-depth-of-binary-tree/description/

思路:求最小深度,需要从上往下找,使用前序遍历,递归终点为叶子节点,到达叶子节点进行判断。

java 复制代码
class Solution {
    int min = Integer.MAX_VALUE;
    public int minDepth(TreeNode root) {
        if(root == null) return 0;
        traverse(root, 1);
        return min;
    }

    void traverse(TreeNode root, int deep) {
        if(root == null) return;
        if(root.left == null && root.right == null) {
            min = Math.min(min, deep);
            return ;
        }
        traverse(root.left, deep+1);
        traverse(root.right, deep+1);
    }
}

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

题目链接:https://leetcode.cn/problems/count-complete-tree-nodes/description/

思路:求完全二叉树的节点个数,思路很简单,就是利用完全二叉树的性质,可以根据深度计算个数,所以就前序遍历,每一个节点都判断是否是完全二叉树,是就不遍历了,不是再遍历。

java 复制代码
class Solution {
    public int countNodes(TreeNode root) {
        if(root == null) return 0;
        int a = 0, b = 0;
        TreeNode p = root, q = root;
        while(p != null) {
            a++;
            p = p.left;
        }
        while(q != null) {
            b++;
            q = q.right;
        }
        if(a == b) return (int)Math.pow(2, a) - 1;
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
}

六、110. 平衡二叉树

题目链接:https://leetcode.cn/problems/balanced-binary-tree/description/

思路:平衡二叉树是指左右子高度相差不超过1,所以直接按照求树的深度就可以解题,只要左右深度大于1,即不平衡。

java 复制代码
class Solution {
    boolean flag = true;
    public boolean isBalanced(TreeNode root) {
        traverse(root);
        return flag;
    }

    int traverse(TreeNode root) {
        if(root == null) return 0;
        int left = traverse(root.left);
        int right = traverse(root.right);
        if(Math.abs(left - right) > 1) {
            flag = false;
        }
        return Math.max(left, right) + 1;
    }
}

七、257. 二叉树的所有路径

题目链接:https://leetcode.cn/problems/binary-tree-paths/description/

思路:求所有路径,这种题目在回溯中非常常见,所以本题也是在递归的过程中使用回溯,在叶子节点进行路径组装。

java 复制代码
class Solution {
    List<String> result = new ArrayList<>();
    List<Integer> list = new ArrayList<>();
    public List<String> binaryTreePaths(TreeNode root) {
        traverse(root);
        return result;
    }
    void traverse(TreeNode root) {
        list.add(root.val);
        if(root.left == null && root.right == null) {
            StringBuilder sb = new StringBuilder();
            for(int i : list) {
                sb.append(i).append("->");
            }
            sb.delete(sb.length()-2, sb.length());
            result.add(sb.toString());
            return;
        }
        
        if(root.left != null) {
            traverse(root.left);
            list.remove(list.size()-1);
        }
        if(root.right != null) {
            traverse(root.right);
            list.remove(list.size()-1);
        }
    }
}

八、404. 左叶子之和

题目链接:https://leetcode.cn/problems/sum-of-left-leaves/description/

思路:求左叶子之和,求的是所有的左叶子的和,所以只需要做两件事情,一件是在叶子节点进行判断,另外一件是提供每个节点的信息,用于判断当前节点是否是叶子节点,这种信息需要从父节点传递,所以在递归函数的参数中。

java 复制代码
class Solution {
    int sum = 0;
    public int sumOfLeftLeaves(TreeNode root) {
        traverse(root, false);
        return sum;
    }

    void traverse(TreeNode root, boolean flag) {
        if(root == null) return ;
        if(root.left == null && root.right == null && flag) {
            sum += root.val;
        }
        traverse(root.left, true);
        traverse(root.right, false);
    }
}

九、513. 找树左下角的值

题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/description/

思路:本题和上一题略有差异,上一题是求所有左叶子节点的和,要求的是左叶子节点,本题类似于树的左视图,但是是深度最深的哪一行的最左边的那个节点,它可能是左节点也可能是右节点。只需要前序遍历,利用深度,当深度第一次大于记录值时,说明是第一次到达下一层,而且采用的是前序遍历,到达的是下一层的最左边的叶子节点。

java 复制代码
class Solution {
    int result = 0, max = 0;
    public int findBottomLeftValue(TreeNode root) {
        traverse(root, 1);
        return result;
    }
    void traverse(TreeNode root, int deep) {
        if(root == null) return ;
        if(root.left == null && root.right == null && deep > max) {
            max = deep;
            result = root.val;
        } 
        traverse(root.left, deep + 1);
        traverse(root.right, deep + 1);
    }
}

十、112. 路径总和

题目链接:https://leetcode.cn/problems/path-sum/description/

思路:求路径总和,类似于回溯的用法,就是在树的递归过程中使用回溯,如果是全局变量,需要手动回滚数据,如果是携带是函数参数列表则不需要。

java 复制代码
class Solution {
    boolean flag = false;
    public boolean hasPathSum(TreeNode root, int targetSum) {
        traverse(root, targetSum, 0);
        return flag;
    }
    void traverse(TreeNode root, int targetSum, int sum) {
        if(root == null || flag) return;
        sum += root.val;
        if(root.left == null && root.right == null) {
            if(sum == targetSum) flag = true;
        }
        traverse(root.left, targetSum, sum);
        traverse(root.right, targetSum, sum);
    }
}
相关推荐
罗西的思考1 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX2 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面2 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号3 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽3 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI3 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者5 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者5 小时前
【征程6】校准量化中HistogramObserver解析
算法
OuO-25 小时前
笔试强训 Day 34:ISBN 号码、kotori 和迷宫、矩阵最长递增路径
java·算法·矩阵
程序喵大人6 小时前
【C++进阶】STL算法与函数对象 - 04 find、count和any_of把查询写成意图
开发语言·c++·算法