【LeetCode | 第四篇】算法笔记

目录

二叉树

二叉树的中序遍历

二叉树的最大深度

翻转二叉树

对称二叉树

二叉树的直径


【LeetCode | 第三篇】算法笔记https://blog.csdn.net/h52412224/article/details/158689782?spm=1001.2014.3001.5502【LeetCode | 第二篇】算法笔记https://blog.csdn.net/h52412224/article/details/158467673?spm=1001.2014.3001.5502【LeetCode | 第一篇】算法笔记https://blog.csdn.net/h52412224/article/details/157903186


二叉树

二叉树的中序遍历

思路 1: 递归

递归 终止条件 :当当前节点为 null 时,直接返回(无节点可访问)。

递归 逻辑

  • 先递归遍历当前节点的左子树

  • 访问当前节点(将值加入结果列表);

  • 再递归遍历当前节点的右子树

java 复制代码
public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        inorderHelper(root, result);
        return result;
    }
 
    private void inorderHelper(TreeNode node, List<Integer> result) {
        if (node == null) {
            return; // 终止条件:空节点直接返回
        }
        inorderHelper(node.left, result); // 1. 遍历左子树
        result.add(node.val); // 2. 访问根节点
        inorderHelper(node.right, result); // 3. 遍历右子树
    }
}

思路 2:迭代法

初始化一个栈和结果列表,定义指针 curr 指向根节点;

循环条件:curr != null 或栈不为空;

内层循环:将 curr 及其所有左子节点依次压入栈(模拟递归遍历左子树),直到 currnull

弹出栈顶节点(当前最左节点),访问该节点(加入结果列表);

curr 指向该节点的右子节点(继续遍历右子树)。

java 复制代码
public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> result = new ArrayList<>();
        Deque<TreeNode> stack = new LinkedList<>(); // 双端队列模拟栈
        TreeNode curr = root;
        
        while (curr != null || !stack.isEmpty()) {
            // 1. 遍历所有左子节点,压入栈
            while (curr != null) {
                stack.push(curr);
                curr = curr.left;
            }
            // 2. 弹出栈顶(最左节点),访问
            curr = stack.pop();
            result.add(curr.val);
            // 3. 处理右子树
            curr = curr.right;
        }
        return result;
    }
}

二叉树的最大深度

思路1: 递归

  1. 递归的核心是将问题分解为子问题:一棵树的最大深度 = 1 + 左子树最大深度与右子树最大深度的较大值。

  2. 递归终止条件:当节点为 null 时,深度为 0(空树无节点)。

  3. 分别递归计算左、右子树的深度,取最大值加 1 即为当前树的最大深度。

java 复制代码
public class Solution {
    public int maxDepth(TreeNode root) {
        // 递归终止:空节点深度为0
        if (root == null) {
            return 0;
        }
        // 递归求左子树深度
        int leftDepth = maxDepth(root.left);
        // 递归求右子树深度
        int rightDepth = maxDepth(root.right);
        // 当前节点深度 = 左右子树最大深度 + 1
        return Math.max(leftDepth, rightDepth) + 1;
    }
}

思路2:迭代法

  1. BFS 按层遍历二叉树,每遍历完整一层,深度加 1,最终层数即为最大深度。

  2. 初始化队列,将根节点入队,深度初始为 0。

  3. 循环遍历队列:每次获取当前层节点数量,遍历该层所有节点,将其左右子节点入队;一层遍历完成后深度加 1。

  4. 队列为空时遍历结束,返回深度。

java 复制代码
public class Solution {
    public int maxDepth(TreeNode root) {
        // 空树直接返回0
        if (root == null) {
            return 0;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root); // 根节点入队
        int depth = 0;

        while (!queue.isEmpty()) {
            // 获取当前层节点个数
            int levelSize = queue.size();
            // 遍历当前层所有节点
            for (int i = 0; i < levelSize; i++) {
                TreeNode node = queue.poll();
                // 左子节点非空则入队
                if (node.left != null) {
                    queue.offer(node.left);
                }
                // 右子节点非空则入队
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            depth++; // 一层遍历完成,深度+1
        }
        return depth;
    }
}

翻转二叉树

思路1: 递归

  1. 递归的核心是交换当前节点的左右子树,再递归处理左右子树。

  2. 递归终止条件:当前节点为 null,直接返回。

  3. 交换当前节点的左、右孩子,然后递归翻转左子树、右子树。

java 复制代码
class Solution {
    public TreeNode invertTree(TreeNode root) {
        // 递归终止:空节点无需翻转
        if (root == null) {
            return null;
        }
        // 交换左右子节点
        TreeNode temp = root.left;
        root.left = root.right;
        root.right = temp;
        // 递归翻转左子树
        invertTree(root.left);
        // 递归翻转右子树
        invertTree(root.right);
        return root;
    }
}

思路2:迭代法

  1. 用队列按层遍历二叉树,逐个处理节点。

  2. 初始化队列,将根节点入队。

  3. 循环出队:取出节点,交换其左右孩子,再将左右孩子入队。

  4. 队列为空时遍历结束,返回根节点。

java 复制代码
class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root); // 根节点入队
        while (!queue.isEmpty()) {
            TreeNode node = queue.poll();
            // 交换当前节点左右孩子
            TreeNode temp = node.left;
            node.left = node.right;
            node.right = temp;
            // 左孩子非空则入队
            if (node.left != null) {
                queue.offer(node.left);
            }
            // 右孩子非空则入队
            if (node.right != null) {
                queue.offer(node.right);
            }
        }
        return root;
    }
}

对称二叉树

思路:递归法

  1. 对称二叉树要求:根节点左右子树镜像对称。

  2. 定义辅助函数判断两个节点是否镜像:

    1. 两个节点都为 null,返回 true

    2. 一个为 null 一个不为 null,返回 false

    3. 节点值相等,且左节点的左子树与右节点的右子树对称、左节点的右子树与右节点的左子树对称。

  3. 主函数调用辅助函数,传入根节点的左右孩子。

java 复制代码
class Solution {
    public boolean isSymmetric(TreeNode root) {
        // 空树对称
        if (root == null) {
            return true;
        }
        // 判断左右子树是否镜像
        return isMirror(root.left, root.right);
    }
    
    // 辅助函数:判断两个节点是否镜像
    private boolean isMirror(TreeNode left, TreeNode right) {
        // 都为空,对称
        if (left == null && right == null) {
            return true;
        }
        // 一个空一个非空,不对称
        if (left == null || right == null) {
            return false;
        }
        // 值相等 + 子树镜像
        return left.val == right.val 
            && isMirror(left.left, right.right) 
            && isMirror(left.right, right.left);
    }
}

二叉树的直径

思路:递归法

  1. 二叉树直径 = 任意两个节点间最长路径的节点数 - 1(边数)。

  2. 直径一定是某节点的左子树深度 + 右子树深度。

  3. 递归计算每个节点的左右子树深度,同时更新全局最大直径。

  4. 递归返回当前节点的最大深度(供父节点计算)。

java 复制代码
class Solution {
    // 记录最大直径
    private int maxDiameter = 0;
    public int diameterOfBinaryTree(TreeNode root) {
        maxDepth(root);
        return maxDiameter;
    }
    // 递归计算深度,同时更新直径
    private int maxDepth(TreeNode node) {
        if (node == null) {
            return 0;
        }
        // 左子树深度
        int left = maxDepth(node.left);
        // 右子树深度
        int right = maxDepth(node.right);
        // 更新最大直径:左深度 + 右深度
        maxDiameter = Math.max(maxDiameter, left + right);
        // 返回当前节点最大深度
        return Math.max(left, right) + 1;
    }
}

上述内容也同步在我的飞书,欢迎访问

https://my.feishu.cn/wiki/QLauws6lWif1pnkhB8IcAvkhncc?from=from_copylink

如果我的内容对你有帮助,请点赞,评论,收藏。创作不易,你们的支持就是我坚持下去的动力!

相关推荐
counting money5 分钟前
prim算法最小生成树(java)
算法
澈2079 分钟前
C++面向对象:类与对象核心解析
c++·算法
用户6906738819211 分钟前
基于无人机的单目测距系统,平均误差仅2.12%
算法
6Hzlia24 分钟前
【Hot 100 刷题计划】 LeetCode 141. 环形链表 | C++ 哈希表直觉解法
c++·leetcode·链表
dinl_vin27 分钟前
LangChain 系列·(四):RAG 基础——给大模型装上“外脑“
人工智能·算法·langchain
探物 AI1 小时前
【感知·医学分割】当 YOLOv11 杀入医学赛道:先检测后分割的级联架构
算法·yolo·计算机视觉·架构
隔壁大炮1 小时前
Day06-08.CNN概述介绍
人工智能·pytorch·深度学习·算法·计算机视觉·cnn·numpy
白云千载尽1 小时前
前馈与反馈——经典控制理论中的基础概念
人工智能·算法
炽烈小老头1 小时前
【每日天学习一点算法 2026/04/27】缺失的第一个正数
学习·算法
handler011 小时前
Linux 进程探索:从 PCB 管理到 fork() 的写时拷贝
linux·c语言·c++·笔记·学习