代码随想录算法训练营第14天| Leetcode 102.二叉树的层序遍历、226.翻转二叉树、101.对称二叉树

目录

Leetcode 102.二叉树的层序遍历

Leetcode 226.翻转二叉树

Leetcode 101.对称二叉树


Leetcode 102.二叉树的层序遍历

题目链接:Leetcode 102.二叉树的层序遍历

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

思路:因为要一层一层遍历,因此需要利用队列辅助。因为队列先进先出符合一层一层遍历的逻辑。本题仍然有递归法和迭代法,不过虽然有两种方法,底层逻辑是相同的,只不过实现的方式不同。从根节点出发,根据每层节点个数依次将节点按顺序放入队列中,然后进入下一层。

代码如下:(递归法)

class Solution {
public:
    void order(TreeNode* cur, vector<vector<int>>& result, int depth) {
        if (cur == nullptr)
            return;
        //由于递归调用时层数在变化,因此需要加上判断条件防止重复
        if (result.size() == depth)
            result.push_back(vector<int>());
        result[depth].push_back(cur->val);
        order(cur->left, result, depth + 1);
        order(cur->right, result, depth + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) {
        vector<vector<int>> result;
        int depth = 0;
        order(root, result, depth);
        return result;
    }
};

(迭代法)

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != nullptr)//如果根节点不为空,加入根节点
            que.push(root);
        vector<vector<int>> result;
        while (!que.empty()) {//只要队列不为空
            int size = que.size();//保存每一层的大小
            vector<int> vec;
            for (int i = 0; i < size; i++) {//遍历每一层所有节点
                TreeNode* node = que.front();
                que.pop();
                vec.push_back(node->val);
                if (node->left)
                    que.push(node->left);
                if (node->right)
                    que.push(node->right);
            }
            result.push_back(vec);
        }
        return result;
    }
};

Leetcode 226.翻转二叉树

题目链接:Leetcode 226.翻转二叉树

题目描述:给你一棵二叉树的根节点root,翻转这棵二叉树,并返回其根节点。

思路:由于要翻转二叉树,因此将每个节点的左右孩子翻转就可以了。至于遍历方式,dfs和bfs都可以,遍历只是个工具,具体的行为需要根据题意灵活转换。这道题需要注意的是中序遍历并不适合本题,中序遍历会将某些节点的左右孩子翻转两次。为什么呢?首先要知道中序遍历的搜索方式是左中右,当所有的左孩子反转之后,我们将中间节点进行翻转,此时的左孩子变成了右孩子,右孩子变成了左孩子,而按照中序遍历,接下来该访问右孩子,但是此时的右孩子就是之前翻转过的左孩子,这导致了最初的左孩子翻转了两次,右孩子没被翻转

文字看起来很绕对吧?我简单画图举个例子:(图片中箭头代表中序遍历的顺序)

根据这个例子我们可以发现,有两个节点没交换过,有两个节点被交换了两次。不过画图之后我们发现:只要以左中左的遍历方式,仍然可以实现我们想要的“中序遍历”的结果。只不过这样严格意义上不算中序遍历了。

代码如下:(递归dfs,先实现交换再递归,对应前/后序遍历)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr)
            return root;
        swap(root->left, root->right); //中
        //这两行顺序可以改变
        invertTree(root->left);  //左
        invertTree(root->right); //右
        return root;
    }
};

(递归bfs)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr)
            return nullptr;
        TreeNode* left = invertTree(root->left);
        TreeNode* right = invertTree(root->right);
        //从最深层开始交换,逐渐向上返回
        root->left = right;
        root->right = left;
        return root;
    }
};

(迭代dfs)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        if (root == nullptr)
            return root;
        stack<TreeNode*> st;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            swap(node->left, node->right);
            //这两个顺序可以调换
            if (node->left)
                st.push(node->left);
            if (node->right)
                st.push(node->right);
        }
        return root;
    }
};

(迭代bfs)

class Solution {
public:
    TreeNode* invertTree(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != nullptr)
            que.push(root);
        while (!que.empty()) {
            int size = que.size();
            for (int i = 0; i < size; i++) {
                TreeNode* node = que.front();
                que.pop();
                swap(node->left, node->right);
                if (node->left)
                    que.push(node->left);
                if (node->right)
                    que.push(node->right);
            }
        }
        return root;
    }
};

通过上面代码我们发现,其实本质上解题的基础代码还是二叉树的遍历搜索,唯一有区别的是本题搜索之后需要交换左右孩子节点。

Leetcode 101.对称二叉树

题目链接:​​​​​​Leetcode 101.对称二叉树

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

思路:首先要思考什么叫做二叉树的轴对称?这可不是简单的比较一个节点的左右孩子就可以了,而是要比较一个结点的左子树和右子树的内测和外侧是否相等。

注:上述图片来源于《代码随想录》

上道题我们提到过:遍历只是个工具,具体的行为需要根据题意灵活转换。因此接下来我们需要思考一下这道题该用什么遍历方式。因为要遍历两棵树而且要比较内侧和外侧节点,所以准确的来说是一个树的遍历顺序是左右中,一个树的遍历顺序是右左中。由于中间节点最后遍历,这和后序遍历类似,因此本题用后序遍历来实现。

代码如下:(递归法)

class Solution {
public:
    bool compare(TreeNode* l, TreeNode* r) {
        //首先排除空节点的情况
        if (l == nullptr && r != nullptr)
            return false;
        else if (l != nullptr && r == nullptr)
            return false;
        else if (l == nullptr && r == nullptr)
            return true;
        //再排除数值不相同的情况
        else if (l->val != r->val)
            return false;
        //数值相同,则递归下一层
        bool outside = compare(l->left, r->right);
        bool inside = compare(l->right, r->left);
        bool isSame = outside && inside;
        return isSame;
    }
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr)
            return true;
        return compare(root->left, root->right);
    }
};

(迭代法)

仍然是借助队列来辅助。

class Solution {
public:
    bool isSymmetric(TreeNode* root) {
        if (root == nullptr)
            return true;
        queue<TreeNode*> que;
        //将根节点左右子树的根节点加入队列
        que.push(root->left);
        que.push(root->right);
        while (!que.empty()) {
            TreeNode* lnode = que.front();
            que.pop();
            TreeNode* rnode = que.front();
            que.pop();
            if (!lnode && !rnode)
                continue; //左右节点均为空,说明对称
            //有一个节点为空或者两节点数值不同,说明不对称
            if (!lnode || !rnode || (lnode->val != rnode->val))
                return false;
            que.push(lnode->left);  // 加入左节点左孩子
            que.push(rnode->right); // 加入右节点右孩子
            que.push(lnode->right); // 加入左节点右孩子
            que.push(rnode->left);  // 加入右节点左孩子
        }
        return true;
    }
};

总结:这几天忙着练车和出去玩,进度有点落下了。不过题目难度还可以,二叉树的很多题目都是以遍历为基础,额外的操作简单思考过后也可以轻松解决。还是那句话:遍历只是个工具,具体的行为需要根据题意灵活转换。

最后,如果文章有错误,请在评论区或私信指出,让我们共同进步!

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Unity学习之坦克游戏制作(2)游戏场景的制作

文章目录 1. 基础场景的搭建2. 游戏主面板2.1 拼出面板2.2 创建新面板2.3 设置面板复用2.4 退出界面 3. 坦克基类3.1 创建基类脚本3.1.1 基类基本属性3.1.2 抽象开火函数3.1.3 受伤虚函数3.1.4 死亡虚函数 4 玩家——基础移动旋转摄像机跟随4.1 玩家对象脚本4.2 控制坦克移动4.…

【Docker】实战案例 - CI/CD

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; CI/CD 持续集成(Continuous integration) 是一种软件开发实践&#xff0c;每次集成都通过自动化的构建&#xff08;包括编译&#xff0c;发…

Dockerfile里ADD * 保留原来的目录结构

1、问题 给新模块写Dockerfile&#xff0c;很多静态资源分散在各个目录&#xff0c;于是Dockerfile里我直接一句&#xff1a; ADD ./* /dest/镜像出来后&#xff0c;启动容器&#xff0c;进入容器种后发现&#xff1a;文件拷贝成功&#xff0c;但原来的目录结构都不在了&…

Rabbitmq调用FeignClient接口失败

文章目录 一、框架及逻辑介绍1.背景服务介绍2.问题逻辑介绍 二、代码1.A服务2.B服务3.C服务 三、解决思路1.确认B调用C服务接口是否能正常调通2.确认B服务是否能正常调用A服务3.确认消息能否正常消费4.总结 四、修改代码验证1.B服务异步调用C服务接口——失败2.将消费消息放到C…

2024水资源、智慧城市与绿色发展国际会议(ICWRSCGD 2024)

2024水资源、智慧城市与绿色发展国际会议(ICWRSCGD 2024) 会议简介 2024年国际水资源、智慧城市与绿色发展大会&#xff08;ICWRSCGD 2024&#xff09;将在中国杭州举行。会议聚焦“水资源、智慧城市、绿色发展”这一最新研究领域&#xff0c;致力于促进世界顶级创新者、科学…

01 Redis的特性+下载安装启动

1.1 NoSQL NoSQL&#xff08;“non-relational”&#xff0c; “Not Only SQL”&#xff09;&#xff0c;泛指非关系型的数据库。 键值存储数据库 &#xff1a; 就像 Map 一样的 key-value 对。如Redis文档数据库 &#xff1a; NoSQL 与关系型数据的结合&#xff0c;最像关系…

代码随想录算法训练营第十一天 | 二叉树基础

代码随想录算法训练营第十一天 | 二叉树基础 文章目录 代码随想录算法训练营第十一天 | 二叉树基础1 二叉树的理论基础1.1 二叉树的类型1.2 二叉树的存储方式1.3 二叉树的遍历方式1.4 二叉树的定义 2 二叉树的递归遍历2.1 前序遍历2.2 中序遍历2.3 后序遍历 3 二叉树的迭代遍历…

C++特殊类的设计

目录 一、不能被拷贝的类 二、只能在堆上创建对象的类 三、只能在栈上创建对象的类 四、不能被继承的类 五、只能创建一个对象的类(单例模式) 下面说几种特殊要求的类的设置&#xff0c;主要学习其中所运用的一些思想&#xff0c;融会贯通 一、不能被拷贝的类 C98可以将拷…

高质量谷歌seo外链平台有哪些?

明确的说&#xff0c;没有任何必要&#xff0c;这里说的没必要指的是没必要寻找什么高质量的外链平台 所谓高质量的外链平台是什么&#xff1f;你期待在这种平台发外链能获得什么效果&#xff1f;高质量的外链平台&#xff0c;无非就是网站排名高&#xff0c;能发相关的外链的平…

iOS推送通知

文章目录 一、推送通知的介绍1. 简介2. 通知的分类 二、本地通知1. 本地通知的介绍2. 实现本地通知3. 监听本地通知的点击 三、远程通知1. 什么是远程通知2. 为什么需要远程通知3. 远程通知的原理4. 如何做远程通知5. 远程通知证书配置6. 获取远程推送要用的 DeviceToken7. 测试…

外贸SOHO产品怎么选?海洋建站选品方法?

外贸SOHO应该如何选产品&#xff1f;跨境电商独立站选品策略&#xff1f; 越来越多的人选择通过外贸SOHO创业&#xff0c;将业务拓展到国际市场。然而&#xff0c;面对琳琅满目的外贸SOHO产品&#xff0c;许多初创企业主可能会感到困惑。海洋建站将为您提供一些建议&#xff0…

直播核心岗位基础内容

一.直播间核心岗位 1.直播间前端岗位 前端岗位分工 &#xff08;1&#xff09;主播岗位职责 &#xff08;2&#xff09;场控岗位职责 &#xff08;3&#xff09;助理岗位职责 中端岗位分工 &#xff08;1&#xff09;运营岗位职责 &#xff08;2&#xff09;中控岗位职责 …

2024年Java SpringBoot 计算机软件毕业设计题目推荐

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和学生毕业项目实战,高校老师/讲师/同行交流合作✌ 主要内容&#xff1a;SpringBoot、Vue、SSM、HLM…

Hbuilder从gitlab上面拉取项目

要先下载TortoiseGit-2.15.0.0-64bit这个软件 在HBuilder中从GitLab上拉取项目&#xff0c;请按照以下步骤操作&#xff1a; 1. 打开HBuilder&#xff0c;点击左上角的“文件”菜单&#xff0c;然后选择“新建”->“项目”。 2. 在弹出的对话框中&#xff0c;选择“从Git导…

解决 [Vue warn]:Avoid mutating a prop directly 警告

错误信息 [Vue warn]: Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop’s value. Prop being mutated: “xxx” 错误原因 所有的 prop 都使得…

vue中使用canvas给图片绘制水印,即使下载图片也是带水印的

先看效果 话不多说直接上组件 1、Watermark.vue <template><div><canvas ref"canvas" :width"width" :height"height"></canvas></div> </template><script>export default {props: {// 图片地址ur…

Java服务端使用freemarker+wkhtmltoimage生成Echart图片

目录 1.通过 freemarker 将ftl转成html 1.1 freemarker 手册: 1.2 添加freemarker maven依赖 1.3 添加 echart-test.ftl 模版文件 1.4 添加 FreemarkerTool 工具类 1.5 添加测试main方法 1.6 运行,生成echart-test-时间戳.html 文件 2. 通过wkhtmltoimage将html 转为p…

【复现】JieLink+智能终端操作平台弱口令漏洞_28

目录 一.概述 二 .漏洞影响 三.漏洞复现 1. 漏洞一&#xff1a; 四.修复建议&#xff1a; 五. 搜索语法&#xff1a; 六.免责声明 一.概述 JeLink智能终端操作平台 (JSOTC2016 fJeLink)是捷顺历经多年行业经验积累&#xff0c;集智能硬件技术视频分析技术、互联网技术等…

【HarmonyOS应用开发】ArkTS基础知识(三)

一、浅析ArkTS的起源和演进 1、引言 Mozilla创造了JS&#xff0c;Microsoft创建了TS&#xff0c;Huawei进一步推出了ArkTS。 从最初的基础的逻辑交互能力&#xff0c;到具备类型系统的高效工程开发能力&#xff0c;再到融合声明式UI、多维状态管理等丰富的应用开发能力&#xf…

如何解决服务器端口被占用的问题,减少带来的影响

在现代网络环境中&#xff0c;服务器扮演着至关重要的角色&#xff0c;其稳定性和安全性对企业的正常运营具有重要意义。然而&#xff0c;服务器端口被占用的问题却时常困扰着企业网络管理员。本文将深入探讨服务器端口被占用的影响&#xff0c;并提出相应的解决方案。 一、服务…