【LeetCode Solutions】LeetCode 101 ~ 105 题解

news2025/4/4 0:00:40

CONTENTS

  • LeetCode 101. 对称二叉树(简单)
  • LeetCode 102. 二叉树的层序遍历(中等)
  • LeetCode 103. 二叉树的锯齿形层序遍历(中等)
  • LeetCode 104. 二叉树的最大深度(简单)
  • LeetCode 105. 从前序与中序遍历序列构造二叉树(中等)

LeetCode 101. 对称二叉树(简单)

【题目描述】

给你一个二叉树的根节点 root,检查它是否轴对称。

【示例 1】

在这里插入图片描述

输入:root = [1,2,2,3,4,4,3]
输出:true

【示例 2】

在这里插入图片描述

输入:root = [1,2,2,null,3,null,3]
输出:false

【提示】

树中节点数目在范围 [ 1 , 1000 ] [1, 1000] [1,1000]
− 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 100<=Node.val<=100

进阶:你可以运用递归和迭代两种方法解决这个问题吗?


【分析】

对称的树具有以下属性之一:

  • 左右子节点均为空;
  • 左右子节点的值相同,且左子节点的左子树与右子节点的右子树相同,左子节点的右子树与右子节点的左子树相同。

因此我们可以递归判断左右子树是否对称。

题目提到用递归和迭代实现,那么如何用迭代实现?

可以用队列维护对称的相对关系,首先将根节点的左右子节点入队,然后不断循环每次从队列中取两个节点,判断这两个节点是否对称,然后将其中一个节点的左/右子节点与另一个节点的右/左子节点对应成两组分别加入到队列中,如果队列为空遍历完整棵树还没发现非对称的节点说明整棵树就是对称的。


【代码】

【递归方法】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        return dfs(root->left, root->right);
    }

    bool dfs(TreeNode* l, TreeNode* r) {
        if (!l && !r) return true;  // 两个节点均为空
        if (!l || !r || l->val != r->val) return false;  // 只有一个节点为空或两个节点值不同
        return dfs(l->left, r->right) && dfs(l->right, r->left);  // 左节点的左/右子树要和右节点的右/左子树对称
    }
};

【迭代方法】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        queue<TreeNode*> Q;
        Q.push(root->left), Q.push(root->right);
        while (!Q.empty()) {
            auto p = Q.front(); Q.pop();
            auto q = Q.front(); Q.pop();
            if (!p && !q) continue;
            if (!p || !q || p->val != q->val) return false;  // 不对称
            Q.push(p->left), Q.push(q->right);  // p 的左子节点需要和 q 的右子节点对称
            Q.push(p->right), Q.push(q->left);  // p 的右子节点需要和 q 的左子节点对称
        }
        return true;  // 全遍历完了说明树是对称的
    }
};

LeetCode 102. 二叉树的层序遍历(中等)

【题目描述】

给你二叉树的根节点 r o o t root root,返回其节点值的层序遍历。(即逐层地,从左到右访问所有节点)。

【示例 1】

在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[9,20],[15,7]]

【示例 2】

输入:root = [1]
输出:[[1]]

【示例 3】

输入:root = []
输出:[]

【提示】

树中节点数目在范围 [ 0 , 2000 ] [0, 2000] [0,2000]
− 1000 < = N o d e . v a l < = 1000 -1000 <= Node.val <= 1000 1000<=Node.val<=1000


【分析】

层序遍历就用一个队列按 BFS 序遍历就行,由于答案需要将每一层的节点分别形成一组值,因此每轮都从队列中出队当前层的所有节点。


【代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> Q;
        if (root) Q.push(root);
        while (!Q.empty()) {
            vector<int> v;  // 当前层的所有节点值
            int cnt = Q.size();  // 当前层的节点数
            while (cnt--) {  // 逐个出队当前层的所有节点
                TreeNode* t = Q.front();
                Q.pop();
                v.push_back(t->val);
                if (t->left) Q.push(t->left);
                if (t->right) Q.push(t->right);
            }
            res.push_back(v);
        }
        return res;
    }
};

LeetCode 103. 二叉树的锯齿形层序遍历(中等)

【题目描述】

给你二叉树的根节点 root,返回其节点值的锯齿形层序遍历。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。

【示例 1】

在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:[[3],[20,9],[15,7]]

【示例 2】

输入:root = [1]
输出:[[1]]

【示例 3】

输入:root = []
输出:[]

【提示】

树中节点数目在范围 [ 0 , 2000 ] [0, 2000] [0,2000]
− 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 100<=Node.val<=100


【分析】

和上一题一样,只需要额外记录一下当前层的结果是否需要翻转即可。


【代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        vector<vector<int>> res;
        queue<TreeNode*> Q;
        if (root) Q.push(root);
        for (bool i = false; !Q.empty(); i ^= true) {  // i 表示当前层是否需要翻转
            vector<int> v;
            int cnt = Q.size();
            while (cnt--) {
                TreeNode* t = Q.front();
                Q.pop();
                v.push_back(t->val);
                if (t->left) Q.push(t->left);
                if (t->right) Q.push(t->right);
            }
            if (i) reverse(v.begin(), v.end());
            res.push_back(v);
        }
        return res;
    }
};

LeetCode 104. 二叉树的最大深度(简单)

【题目描述】

给定一个二叉树 root,返回其最大深度。

二叉树的最大深度是指从根节点到最远叶子节点的最长路径上的节点数。

【示例 1】

在这里插入图片描述

输入:root = [3,9,20,null,null,15,7]
输出:3

【示例 2】

输入:root = [1,null,2]
输出:2

【提示】

树中节点的数量在 [ 0 , 1 0 4 ] [0, 10^4] [0,104] 区间内。
− 100 < = N o d e . v a l < = 100 -100 <= Node.val <= 100 100<=Node.val<=100


【分析】

用 BFS 也就是类似前两题的做法能够求出层数,也可以直接用递归求解,从根节点往下递归求解每个节点的高度,到空节点了高度就为 0,否则当前节点的高度就是左子树与右子树中的最大高度加一(当前节点的高度比子树多 1)。


【代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int maxDepth(TreeNode* root) {  // 返回 root 的最大高度
        if (!root) return 0;
        return max(maxDepth(root->left), maxDepth(root->right)) + 1;
    }
};

LeetCode 105. 从前序与中序遍历序列构造二叉树(中等)

【题目描述】

给定两个整数数组 preorderinorder,其中 preorder 是二叉树的先序遍历,inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

【示例 1】

在这里插入图片描述

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

【示例 2】

输入: preorder = [-1], inorder = [-1]
输出: [-1]

【提示】

1 < = p r e o r d e r . l e n g t h < = 3000 1 <= preorder.length <= 3000 1<=preorder.length<=3000
i n o r d e r . l e n g t h = = p r e o r d e r . l e n g t h inorder.length == preorder.length inorder.length==preorder.length
− 3000 < = p r e o r d e r [ i ] , i n o r d e r [ i ] < = 3000 -3000 <= preorder[i], inorder[i] <= 3000 3000<=preorder[i],inorder[i]<=3000
preorderinorder无重复元素
inorder 均出现在 preorder
preorder 保证为二叉树的前序遍历序列
inorder 保证为二叉树的中序遍历序列


【分析】

根据前序或后序遍历与中序遍历构建二叉树是必须要掌握的基础知识,详细讲解可以转到:【UCB CS 61B SP24】Lecture 22 & 23: Tree and Graph Traversals, DFS, BFS。

简单概括思路就是前序遍历的第一个节点就是根节点,然后在中序遍历中找到根节点就能够区分出根节点的左右子树区间,根据左右子树节点数量再递归创建左右子树。


【代码】

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return build(preorder, 0, preorder.size() - 1, inorder, 0, inorder.size() - 1);
    }

    TreeNode* build(vector<int>& pre, int preSt, int preEd, vector<int>& in, int inSt, int inEd) {
        if (preSt > preEd) return nullptr;
        TreeNode* root = new TreeNode(pre[preSt]);  // 根节点就是前序遍历的第一个节点
        int k = inSt;
        while (in[k] != pre[preSt]) k++;  // 在中序遍历中找到根节点
        int leftChildNum = k - inSt;  // 左子树节点数
        root->left = build(pre, preSt + 1, preSt + leftChildNum, in, inSt, k - 1);
        root->right = build(pre, preSt + leftChildNum + 1, preEd, in, k + 1, inEd);
        return root;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2325547.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Orpheus-TTS 介绍,新一代开源文本转语音

Orpheus-TTS 是由 Canopy Labs 团队于2025年3月19日发布的开源文本转语音&#xff08;TTS&#xff09;模型&#xff0c;其技术突破集中在超低延迟、拟人化情感表达与实时流式生成三大领域。以下从技术架构、核心优势、应用场景、对比分析、开发背景及最新进展等多维度展开深入解…

Java数据结构-栈和队列

目录 1. 栈(Stack) 1.1 概念 1.2 栈的使用 1.3 栈的模拟实现 1.4 栈的应用场景 1. 改变元素的序列 2. 将递归转化为循环 3. 括号匹配 4. 逆波兰表达式求值 5. 出栈入栈次序匹配 6. 最小栈 1.5 概念区分 2. 队列(Queue) 2.1 概念 2.2 队列的使用 2.3 队列模拟实…

权重衰减-笔记

《动手学深度学习》-4.5-笔记 权重衰减就像给模型“勒紧裤腰带”&#xff0c;不让它太贪心、不让它学太多。 你在学英语单词&#xff0c;别背太多冷门单词&#xff0c;只背常见的就行&#xff0c;这样考试时更容易拿分。” —— 这其实就是在“限制你学的内容复杂度”。 在…

Hyperliquid 遇袭「拔网线」、Polymarket 遭治理攻击「不作为」,从双平台危机看去中心化治理的进化阵痛

作者&#xff1a;Techub 热点速递 撰文&#xff1a;Glendon&#xff0c;Techub News 继 3 月 12 日「Hyperliquid 50 倍杠杆巨鲸」引发的 Hyperliquid 清算事件之后&#xff0c;3 月 26 日 晚间&#xff0c;Hyperliquid 再次遭遇了一场针对其流动性和治理模式的「闪电狙击」。…

软考笔记6——结构化开发方法

第六章节——结构化开发方法 结构化开发方法 第六章节——结构化开发方法一、系统分析与设计概述1. 系统分析概述2. 系统设计的基本原理3. 系统总体结构设计 二、结构化分析方法1. 结构化分析方法概述2. 数据流图(DFD)3. 数据字典 三、结构化设计方法&#xff08;了解&#xff…

一种C# Winform的UI处理

效果 圆角 阴影 突出按钮 说明 这是一种另类的处理&#xff0c;不是多层窗口 也不是WPF 。这种方式的特点是比较简单&#xff0c;例如圆角、阴影、按钮等特别容易修改过。其实就是html css DirectXForm。 在VS中如下 圆角和阴影 然后编辑这个窗体的Html模板&#xff0c…

为什么视频文件需要压缩?怎样压缩视频体积即小又清晰?

在日常生活中&#xff0c;无论是为了节省存储空间、便于分享还是提升上传速度&#xff0c;我们常常会遇到需要压缩视频的情况。本文将介绍为什么视频需要压缩&#xff0c;压缩视频的好处与坏处&#xff0c;并教你如何使用简鹿视频格式转换器轻松完成MP4视频文件的压缩。 为什么…

Nginx — Nginx处理Web请求机制解析

一、Nginx请求默认页面资源 1、配置文件详解 修改端口号为8080并重启服务&#xff1a; 二、Nginx进程模型 1、nginx常用命令解析 master进程&#xff1a;主进程&#xff08;只有一个&#xff09; worker进程&#xff1a;工作进程&#xff08;可以有多个&#xff0c;默认只有一…

5.0 WPF的基础介绍1-Grid,Stack,button

WPF: Window Presentation Foundation. WPF与WinForms的对比如下&#xff1a; 特性WinFormsWPF技术基础基于传统的GDI&#xff08;图形设备接口&#xff09;基于DirectX&#xff0c;支持硬件加速的矢量渲染UI设计方式拖拽控件事件驱动代码&#xff08;简单但局限&#xff09;…

Docker 端口映射原理

在 Docker 中&#xff0c;默认情况下容器无法直接与外部网络通信。 为了使外部网络能够访问容器内的服务&#xff0c;Docker 提供了端口映射功能&#xff0c;通过将宿主机的端口映射到容器内的端口&#xff0c;外部可以通过宿主机的IP和端口访问容器内的服务 以下通过动手演示…

SDL —— 将sdl渲染画面嵌入Qt窗口显示(附:源码)

🔔 SDL/SDL2 相关技术、疑难杂症文章合集(掌握后可自封大侠 ⓿_⓿)(记得收藏,持续更新中…) 效果 使用QWidget加载了SDL的窗口,渲染器使用硬件加速跑GPU的。支持Qt窗口缩放或显示隐藏均不影响SDL的图像刷新。   操作步骤 1、在创建C++空工程时加入SDL,引入头文件时需…

算法每日一练 (23)

&#x1f4a2;欢迎来到张翊尘的技术站 &#x1f4a5;技术如江河&#xff0c;汇聚众志成。代码似星辰&#xff0c;照亮行征程。开源精神长&#xff0c;传承永不忘。携手共前行&#xff0c;未来更辉煌&#x1f4a5; 文章目录 算法每日一练 (23)最大正方形题目描述解题思路解题代码…

UE5学习笔记 FPS游戏制作28 显式玩家子弹数

文章目录 添加变量修改ShootOnce方法&#xff0c;设计时减少子弹&#xff0c;没有子弹不能开枪在UI上显示 添加变量 在Gun类中添加BulletNum和ClipSize两个参数 BulletNum是当前还有多少子弹&#xff0c;ClipSize是一个弹匣多少子弹 Rifle的ClipSzie设置为30&#xff0c;Laun…

《构建有效的AI代理》学习笔记

原文链接:https://www.anthropic.com/engineering/building-effective-agents 《构建有效的AI代理》学习笔记 一、概述 核心结论 • 成功的AI代理系统往往基于简单、可组合的模式&#xff0c;而非复杂框架。 • 需在性能、成本与延迟之间权衡&#xff0c;仅在必要时增加复杂度…

数据处理专题(四)

目标 使用 Matplotlib 进行基本的数据可视化。‍ 学习内容 绘制折线图 绘制散点图 绘制柱状图‍ 代码示例 1. 导入必要的库 import matplotlib.pyplot as pltimport numpy as npimport pandas as pd 2. 创建示例数据集 # 创建示例数据集data { 月份: [1月, 2月, 3…

【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解

【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解 文章目录 【目标检测】【深度学习】【Pytorch版本】YOLOV1模型算法详解前言YOLOV1的模型结构YOLOV1模型的基本执行流程YOLOV1模型的网络参数YOLOV1模型的训练方式 YOLOV1的核心思想前向传播阶段网格单元(grid cell)…

云钥科技多通道工业相机解决方案设计

项目应用场景分析与需求挑战 1. 应用场景 ‌目标领域‌&#xff1a;工业自动化检测&#xff08;如精密零件尺寸测量、表面缺陷检测&#xff09;、3D立体视觉&#xff08;如物体建模、位姿识别&#xff09;、动态运动追踪&#xff08;如高速生产线监控&#xff09;等。 ‌核心…

从零到一:ESP32与豆包大模型的RTC连续对话实现指南

一、对话效果演示 ESP32与豆包大模型的RTC连续对话 二、ESP-ADF 介绍 乐鑫 ESP-ADF&#xff08;Espressif Audio Development Framework&#xff09;是乐鑫科技&#xff08;Espressif Systems&#xff09;专为 ESP32 系列芯片开发的一款音频开发框架。它旨在简化基于 ESP32 芯…

【深度学习与实战】2.3、线性回归模型与梯度下降法先导案例--最小二乘法(向量形式求解)

为了求解损失函数 对 的导数&#xff0c;并利用最小二乘法向量形式求解 的值‌ 这是‌线性回归‌的平方误差损失函数&#xff0c;目标是最小化预测值 与真实值 之间的差距。 ‌损失函数‌&#xff1a; 考虑多个样本的情况&#xff0c;损失函数为所有样本的平方误差之和&a…

【Django】教程-2-前端-目录结构介绍

【Django】教程-1-安装创建项目目录结构介绍 3. 前端文件配置 3.1 目录介绍 在app下创建static文件夹, 是根据setting中的配置来的 STATIC_URL ‘static/’ templates目录&#xff0c;编写HTML模板&#xff08;含有模板语法&#xff0c;继承&#xff0c;{% static ‘xx’ …