【二叉树OJ】常见面试题

news2024/9/22 9:39:59

文章目录

  • 1.[单值二叉树](https://leetcode.cn/problems/univalued-binary-tree/description/)
    • 1.2 题目要求
    • 1.3 深度优先搜索
  • 2.[相同的树](https://leetcode.cn/problems/same-tree/)
    • 2.1 题目要求
    • 2.2 深度优先遍历
  • 3.[对称二叉树](https://leetcode.cn/problems/symmetric-tree/description/)
    • 3.1 题目要求
    • 3.2 深度优先遍历利用相同的树
  • 4.[二叉树的前序遍历](https://leetcode.cn/problems/binary-tree-preorder-traversal/description/)
    • 4.1 题目要求
    • 4.2 递归方法
  • 5.二叉树的中序遍历
    • 5.1 题目要求
    • 5.2 递归方法
  • 6.[二叉树的后序遍历](https://leetcode.cn/problems/binary-tree-postorder-traversal/)
    • 6.1 题目要求
    • 6.2 递归方法
    • 6.3 迭代方法
  • 7.[另一棵树的子树](https://leetcode.cn/problems/subtree-of-another-tree/description/)
    • 7.1 题目要求
    • 7.2 深度优先搜索

1.单值二叉树

单值二叉树

1.2 题目要求

判断所给树的值是否唯一

1.3 深度优先搜索

如何判断单值二叉树树,当且仅当当前节点的左子树和右子树的值都等于当前节点的值。然后根据等值的传递性,所有的树就会相等。
为此我们可以运用深度优先遍历的算法,判断当前节点的左右子树的值是否与当前节点相等(注意判断左右子树是否存在),不相等就返回false,相等的话就进行进入二叉树的下一层继续判断,直到最后将结果返回。

bool isUnivalTree(struct TreeNode* root) {
    if(root==NULL)
        return true;
    int cur_val = root->val;
    if(root->left&&root->left->val!=cur_val)//在存在左子树的情况下判断左子树的值是否与当前节点值相等
        return false;
    if(root->right&&root->right->val!=cur_val)//在存在右子树的情况下判断右子树的值是否与当前节点值相等
        return false;
    return isUnivalTree(root->left)&&isUnivalTree(root->right);
}

2.相同的树

相同的树

2.1 题目要求

判断两棵树是否相同

2.2 深度优先遍历

现在我们开始考虑经过的每个节点的情况:可以分为3种

  1. p节点和q节点都为NULL,p节点与q节点相同,返回true
  2. p节点和q节点有一个为NULL,p节点与q节点不相同,返回false
  3. p节点和q节点两个都不为NULL,但不相同的情况,返回false
  4. p节点和q节点两个都不为NULL,但相同的情况,继续查找其下一层左右子树
    了解完这三种情况,写成代码就很简单了。运用深度优先遍历,递归地判断两个二叉树是否相同。
bool isSameTree(struct TreeNode* p, struct TreeNode* q) {
    if(p==NULL&&q==NULL)
        return true;
    else if(p==NULL||q==NULL)
        return false;
    else if(p->val!=q->val)
        return false;
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}

3.对称二叉树

对称二叉树

3.1 题目要求

判断二叉树是否为对称二叉树

3.2 深度优先遍历利用相同的树

要判断一个二叉树是否对称还是很简单的,就是判断该节点的左右子树是否"相等"。因为对称的缘故,左右子树的相等应该是镜像相同,那么是不是可以用我们上一题的代码再稍微修改一下呢?
这里的镜像相等也是分为4种情况:

  1. p节点和q节点都为NULL,p节点与q节点相同,返回true
  2. p节点和q节点有一个为NULL,p节点与q节点不相同,返回false
  3. p节点和q节点两个都不为NULL,但不相同的情况,返回false
  4. p节点和q节点两个都不为NULL,但相同的情况,继续查找其下一层左右子树
    唯一不同的就是4的步骤,在传递p的左子树时我们要传递q的右子树,那么传递p的右子树时就需要传递q的左子树了。
bool dfs(struct TreeNode*p,struct TreeNode*q)
{
    if(p==NULL&&q==NULL)
        return true;
    else if(p==NULL||q==NULL)
        return false;
    else if(p->val!=q->val)
        return false;
    return dfs(p->left,q->right)&&dfs(p->right,q->left);
}

bool isSymmetric(struct TreeNode* root) {
    return dfs(root->left,root->right);
}

4.二叉树的前序遍历

二叉树

4.1 题目要求

按照二叉树的前序遍历将二叉树的值存放到数组中。

4.2 递归方法

这里就将一下,力扣的C语言返回数组的题基本都需要更新returnSize的值,相同会根据这个值判断你返回数组的有效元素个数。在后面用C++后就在需要了

void treepre(int* a,struct TreeNode* root,int*i)
 {
     if(!root)
     {
         return;
     }
     *(a+(*i)++) = root->val;
     treepre(a,root->left,i);
     treepre(a,root->right,i);
     return;

 }
int* preorderTraversal(struct TreeNode* root, int* returnSize) {
    int* a = (int*)malloc(sizeof(int)*100);
    int i = 0;
    treepre(a,root,&i);
    *returnSize = i;
    return a;
}
//C++版
class Solution {
public:
void _dfs(TreeNode* root,vector<int>&res)
{
    if(!root) return;
    res.push_back(root->val);
    _dfs(root->left,res);
    _dfs(root->right,res);
}
    vector<int> preorderTraversal(TreeNode* root) {
        vector<int> res;
        _dfs(root,res);
        return res;
    }
};

5.二叉树的中序遍历

二叉树

5.1 题目要求

按照二叉树的中序遍历将二叉树的值存放到数组中

5.2 递归方法

参考前序遍历就好。

 void treepre(int* a,struct TreeNode* root,int*i)
 {
     if(!root)
     {
         return;
     }
     treepre(a,root->left,i);
     *(a+(*i)++) = root->val;
     treepre(a,root->right,i);
     return;

 }
int* inorderTraversal(struct TreeNode* root, int* returnSize) {
    int* a = (int*)malloc(sizeof(int)*100);
    int i = 0;
    treepre(a,root,&i);
    *returnSize = i;
    return a;
}

6.二叉树的后序遍历

二叉树

6.1 题目要求

按照二叉树的后序遍历将二叉树的值存放到数组中

6.2 递归方法

参考中序遍历题

 void treepre(int* a,struct TreeNode* root,int*i)
 {
     if(!root)
     {
         return;
     }
     treepre(a,root->left,i);
     treepre(a,root->right,i);
     *(a+(*i)++) = root->val;

     return;

 }

int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    int* a = (int*)malloc(sizeof(int)*100);
    int i = 0;
    treepre(a,root,&i);
    *returnSize = i;
    return a;
}

6.3 迭代方法

我们也可以用迭代的方式实现方法一的递归函数,两种方式是等价的,区别在于递归的时候隐式地维护了一个栈,而我们在迭代的时候需要显式地将这个栈模拟出来,其余的实现与细节都相同,具体可以参考下面的代码。

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* prev = nullptr;
        vector<int> ans;
        while(cur||!st.empty())
        {
            while(cur)//去左树
            {
                st.push(cur);
                cur = cur->left;
            }
            
            TreeNode* tmp = st.top();
            if(tmp->right == nullptr||tmp->right == prev)
            {
                ans.push_back(tmp->val);
                st.pop();
            }
            else
            {
                cur = tmp->right;
            }
            prev = tmp;
            
        }
        return ans;
    }
};

7.另一棵树的子树

另一颗的子树

7.1 题目要求

判断 root 中是否包含和 subRoot 具有相同结构和节点值的子树

7.2 深度优先搜索

因为题目要我们找root中是否存在一个子树是subRoot,我们直接枚举root的每一个节点然后和subRoot进行相同二叉树的判断。为此写这题只要知道遍历二叉树和相同二叉树的判断就可以了
在递归遍历二叉树的过程中如果root的值等于subRoot就可以进入二叉树判断环节了,然后相同二叉树判断的题我们已经写过了,结合一下就是了。

bool isSameTree(struct TreeNode* p,struct TreeNode* q)
{
    if(p==NULL&&q==NULL)
        return true;
    else if(p==NULL||q==NULL)
        return false;
    else if(p->val!=q->val)
        return false;
    return isSameTree(p->left,q->left)&&isSameTree(p->right,q->right);
}

bool isSubtree(struct TreeNode* root, struct TreeNode* subRoot){
    if(root == NULL)
        return false;
    if(root->val == subRoot->val)
    {
        if(isSameTree(root,subRoot))
            return true;
    }
    return isSubtree(root->left,subRoot)||isSubtree(root->right,subRoot);
}

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

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

相关文章

热敏打印机ESC指令封装-SAAS本地化及未来之窗行业应用跨平台架构

一热敏打印机ESC指令 它包含了一系列的控制指令&#xff0c;通过这些指令可以实现对打印内容的格式设置&#xff0c;如字体大小、加粗、下划线、对齐方式等。还能够控制打印的位置、纸张进纸、切纸等操作。 例如&#xff0c;在商业零售场景中&#xff0c;收银小票打印机就是基…

刷到好听的音频怎么办

在短视频平台上&#xff0c;我们常常会刷到那些好听得让人陶醉的视频&#xff0c;可却无法直接下载保存其中的音频&#xff0c;是不是感觉很遗憾&#xff1f; 比如刷到林俊杰这首前奏超好听的《江南》&#xff0c;却禁止下载无法直接下载保存。 别担心&#xff0c;下面就为您揭…

html页面缩放自适应

html页面缩放自适应 一、为什么页面要进行缩放自适应 在我们一般web端进行页面拼接完成后&#xff0c;在web端的显示正常&#xff08;毕竟我们是按照web端进行页面拼接完成的&#xff09;&#xff0c;那么要是用其他设备打开呢&#xff0c;比如手机或者平板&#xff0c;这时候…

聚鼎科技:新手做装饰画生意卖什么比较好

在艺术的广阔天地里&#xff0c;装饰画以其独特的魅力逐渐成为室内装饰不可或缺的元素。对于刚入行的新手而言&#xff0c;选择合适的装饰画产品至关重要&#xff0c;它关系到业务的成功与否。以下是一些关于新手做装饰画生意卖什么比较好的建议。 考虑到市场需求的多样性&…

宝兰德荣获openEuler项目群青铜捐赠人称号,共筑开源生态繁荣新篇章

近日&#xff0c;开放原子开源基金会正式公布了新增捐赠人名单&#xff0c;宝兰德凭借在开源领域的卓越贡献与深厚实力&#xff0c;被授予openEuler项目群青铜捐赠人称号。 开放原子开源基金会是致力于推动全球开源事业发展的非营利机构&#xff0c;于2020年6月在北京成立。开放…

Vue3+Vite项目从零搭建+安装依赖+配置按需导入

环境准备 Vscode/HBuilder等任何一种前端开发工具node.js&npm本地开发环境 源代码管理&#xff1a;Git 技术栈 项目构建 创建项目 npm create vite依次运行最后三行出现&#xff0c;成功启动项目在浏览器输入 http://localhost:5173/ 可以显示页面 src别名的配置 在…

xcode14.2学习笔记 swift5开发macos网络程序笔记

1. .frame(width: 200.0, height: 200.0) 控制默认窗体大小 2.去除Metal API Validation提示 Product->Scheme > Edit Scheme... > Run > Diagnostics > Metal API Validation. 3.本地安装git依赖资源&#xff08;可能有的时候并不好用&#xff0c;显示不出自…

星露谷模组开发教程#6 烹饪和制造配方

首发于Enaium的个人博客 在上篇文章中我们添加了一个新的食物&#xff0c;但是这个食物并没有配方&#xff0c;所以我们今天来添加一个配方。 烹饪配方 我们在Data/CookingRecipes.json中可以看到所有的食物配方&#xff0c;所以我们需要修改这个配置文件来添加我们的食物配方…

基于Vue2使用x2js将JSON转换成XML、将XML转换成JSON

x2js源码地址GitHub - abdolence/x2js: x2js - XML to JSON and back for JavaScriptx2js - XML to JSON and back for JavaScript. Contribute to abdolence/x2js development by creating an account on GitHub.https://github.com/abdolence/x2js import x2js from x2js;//…

go语言后端开发学习(四) —— 在go项目中使用Zap日志库

一.前言 在之前的文章中我们已经介绍过如何使用logrus包来作为我们在gin框架中使用的日志中间件&#xff0c;而今天我们要介绍的就是我们如何在go项目中如何集成Zap来作为日志中间件 二.Zap的安装与快速使用 和安装其他第三方包没什么区别&#xff0c;我们下载Zap包只需要执…

Github Actions自动发布release

目录 说明正文1.设置仓库密钥2.打开仓库权限3.配置自动化文件4.写在最后 说明 GitHub Actions 是 GitHub 的持续集成服务&#xff0c;于2018年10月推出。通过Github Actions可以实现诸多自动化功能&#xff0c;比如自动打包&#xff0c;自动发布Release等等。除此之外&#xf…

实验10-3 递归计算Ackermenn函数

本题要求实现Ackermenn函数的计算&#xff0c;其函数定义如下&#xff1a; 函数接口定义&#xff1a; int Ack( int m, int n ); 其中m和n是用户传入的非负整数。函数Ack返回Ackermenn函数的相应值。题目保证输入输出都在长整型范围内。 输入样例&#xff1a; 2 3输出样例&am…

8 个最佳 Java IDE 和文本编辑器

从 2024 年使用的最佳 Java IDE 和代码编辑器中进行选择&#xff0c;并提高您的 Java 生产力。 Java 是世界上最流行的编程语言之一&#xff0c;于 1995 年首次推出&#xff0c;它确实践行了“编写一个&#xff0c;随处运行”的座右铭。该语言用途广泛&#xff0c;可用于构建从…

浅谈物理集中式数据中台架构在数据开发中的不足

在传统数据开发和生产领域&#xff0c;企业面临的问题主要源于数据规模的急剧增长&#xff0c;多源异构数据的不断扩张&#xff0c;以及数据消费端看数、用数的人员越来越多。初期&#xff0c;数据仓库的主要功能聚焦于支持经营仪表盘的视图构建&#xff0c;旨在为企业提供直观…

ubuntu:最新安装使用docker

前言 系统&#xff1a;ubuntu 22.04 desktop 目的&#xff1a;安装使用docker 安装小猫猫 没有安装包的&#xff0c;可以自己去瞅瞅&#xff0c;这里不提供下载方式 sudo dpkg -i ./cat-verge_1.7.5_amd64.deb 在应用里&#xff0c;打开这个软件&#xff0c;并开启系统猫猫 配…

单元训练08:外部中断的基本操作

蓝桥杯 小蜜蜂 单元训练08&#xff1a;外部中断的基本操作 #include "stc15f2k60s2.h"#define LED(x) \{ \P0 x; \P2 P2 & 0x1f | 0x80; \P2 & 0x1f; \}#define L1 0xFE; // 定义L1亮…

SpringBoot集成MyBatis和FlyWay

一、什么是FlyWay 一个开源的数据库迁移工具&#xff0c;用于管理和执行数据库结构的版本变更。通俗来说&#xff0c;它帮助开发者跟踪和应用数据库中的更改&#xff0c;比如表的创建、列的修改等。主要的功能为&#xff1a; 数据库版本控制&#xff1a; Flyway 使用一组迁移…

硬件I2C和软件I2C(模拟I2C)的区别

硬件I2C和软件I2C是两种不同的实现I2C&#xff08;Inter-Integrated Circuit&#xff0c;集成电路间&#xff09;通信协议的方式&#xff0c;它们在实现方式、性能特点以及应用场景上存在显著差异。 一、实现方式 硬件I2C&#xff1a;通过专门的硬件电路实现&#xff0c;这些…

泛交通领域的可视化大屏作品欣赏,各个都相当惊艳。

各位新老朋友大家好&#xff0c;本次给大家带来泛交通领域的可视化大屏&#xff0c;供大家鉴赏。 泛交通领域是指综合利用各种交通方式和资源&#xff0c;提供全方位、多元化的出行选择和服务的交通体系。 它包括以下几个方面&#xff1a; 1. 公共交通&#xff1a;包括地铁、…

花钱买不到系列之—linux系统调用

关于系统调用是什么&#xff0c;为什么用系统调用? 也是通过生活的例子来说明白。 我们生活中有一种东西叫银行&#xff0c;银行是不是有存钱的仓库对不对&#xff1f;好银行有存钱的仓库&#xff0c;银行有桌椅板凳啊&#xff0c;银行还有电脑&#xff0c;设备啊&#xff0c;…