当前位置: 首页 > news >正文

【LeetCode Solutions】LeetCode 101 ~ 105 题解

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;
    }
};

相关文章:

  • 加载MiniLM-L12-v2模型及知识库,调用Deepseek进行问答
  • 全面解析 Spring AOP 切入点表达式
  • 【导航定位】GNSS数据说明-RTCM
  • RabbitMQ高级特性--TTL和死信队列
  • socket演示程序3(udp)
  • 《符号之纱与血肉之躯:具身智能范式的哲学重构与AI发展新图景》
  • 透过TCP/IP看HTTP
  • 深度学习篇---模型GPU训练
  • 监控平台——SkyWalking部署
  • Spring AOP中为所有类型通知传递参数的完整示例,包含详细注释和参数传递方式
  • 【数据结构】哈夫曼树
  • 74. Linux设备树详解
  • 基于springboot课程学习与互动平台(源码+lw+部署文档+讲解),源码可白嫖!
  • SQL注入点判断数据库类型
  • 从“制造”到“智造”:生产线自动检测的技术变革与实践
  • 【力扣hot100题】(017)矩阵置零
  • 火山引擎智能数据洞察 ChatBI 适配 DeepSeek-R1 及 DeepSeek-V3
  • 【商城实战(75)】数据分析指标体系搭建:从0到1的技术指南
  • 基于Halcon仿VM流程列表的执行效果
  • 深入解析MapReduce工作流程:从核心原理到实战优化
  • 济南优化网站的哪家好/西安网站seo诊断
  • 深圳科源建设集团有限公司网站/seo关键词排名优化软件
  • 南宁微信网站制作/推广普通话手抄报模板
  • 旅游网页设计模板下载/系统优化软件推荐
  • 淄博网站建设0533cl/中国优秀网页设计案例
  • 淘客网站如何做推广/营销推广是干什么的