二叉树进阶经典笔试题_1

1. 二叉树创建字符串

题目链接:606. 根据二叉树创建字符串 - 力扣(LeetCode)

题目描述:给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。空节点使用一对空括号对 "()" 表示,转化后需要省略所有不影响字符串与原始二叉树之间的一对一映射关系的空括号对。

 题目:给一个根节点,前序遍历:根节点,左子树,右子树。给了一个根节点,是TreeNode*,最后的返回值是string。

思路:1.使用to_string进行一次转换(root->val)

           2.前序遍历:根节点,左节点,右节点。

  • 如果左节点不为空,将这个根节点先拿到,然后递归遍历这个节点的左子树。
  • 如果左节点为空,右节点不为空。拿到右节点,再去递归遍历右节点的左子树。
  • 如果左节点为空,右节点为空,返回一个空字符串

左右节点只要有一个不为空,就不能省略左节点的()。判断条件是if(root->left || root->right)。已经遍历完所有的根节点和左子树。接下来要访问右子树,如果右节点不为空,就去访问右节点的右子树并加上()

class Solution {
public:
    string tree2str(TreeNode* root) {

        if(root == nullptr)
            return "";
        string str = to_string(root->val);
        
        //如果左节点不为空,遍历左节点的左子树
        //如果左节点为空,遍历右节点的左子树
        if(root->left ||  root->right)
        {
            str +='(';
            str+= tree2str(root->left);
            str+= ')';
        }
       
       //遍历右节点的右子树
       if(root->right)
       {
           str +='(';
           str+=tree2str(root->right);
           str+=')';
       }

        return str;
    }
};

2. 二叉树的分层遍历I

题目链接:https://leetcode.cn/problems/binary-tree-level-order-traversal/

题目描述:给一个二叉树的根节点root,返回层序遍历。逐层从左到右访问所有节点

 分析:形参是root,返回值是一个vector<vector<int>>, 一层放入一个vector<int>里面,出完一层,放入vector<vector<int>>中,所以要定义两个vector,vector<int> v, vector<vector<int>> vv。判断一层是否出完:用一个levelsize去判断,队列为空的时候,这层就出完了。那如何去统计这个levelsize?如何判断所有的节点都出完了?

思考1:当 3出队列,第一层出完,此时队列为空,9,20入队列,队列中节点的个数就是这层节点数,9出队列,20出队列,此时队列为空,15,7入队列。队列中节点的大小就是这层节点数。

思考2:当队列为空,所有的节点都出完了,可以reutrn vv。

class Solution{
pubilc:

vector<vector<int>> levelOrder(TreeNode * root)
{
   // vector<int> v;
    vector<vector<int>> vv;
    int levelsize = 0;
    queue<TreeNode *> q;
    
    //入队列,空的就不入了
    if(root)
     {    
         q.push(root);
        levelsize = 1;
      }
    
    //当队列中还有数据,就继续出 
    while(!q.empty())
    {
        //在这里定义v,每次上来v都是空的
          vector<int > v;
        //一层一层出
        while(levelsize--)
        {
            //这里要用front 因为使用root,pop之后,就无法更新
            //front每次都是头节点
          TreeNode * front =  q.front();
            v.push(front ->val);
            q.pop();
            if(front ->left)
                q.push(front->left);
            if(q->right)
                q.push(front->right);
         }
    
        //一层出完,统计当前队列中的个数
        levelsize = q.size();
        //放入vv中
        vv.push_back(v);
    }
        
        return vv;
}
};

3. 二叉树的分层遍历II

题目链接:力扣

题目描述:给你二叉树的根节点 root ,返回其节点值 自底向上的层序遍历 。 (即按从叶子节点所在层到根节点所在的层,逐层从左向右遍历)

分析:这道题也是层序遍历,和上一道题不同就是自底向上遍历,观察以下它的输出,和正序遍历就是一个逆置的关系,所以使用一个reverse即可解决问题。

reverse(vv.begin(),vv.end());

4. 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先

题目描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

题目链接:236. 二叉树的最近公共祖先 - 力扣(LeetCode)

分析:首先先看到的是根节点,如果这两个节点都在根节点的左子树,那么就继续判断根节点的左节点,再去判断这两个节点是否在这个节点的左,右子树,如果是,则这个节点就是最近的公共祖先,如果不是,那么继续判断,如果在右树,就找当前节点的右节点,继续判断。使用递归的思想

class Solution {
public:
    bool IsInTree(TreeNode * root, TreeNode * x)
    {
        if(root == nullptr)
            return false;
        if(x == root)
            return true;
        else
        {
          return  IsInTree(root->left,x) || IsInTree(root->right,x);
        }
    }
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == nullptr)
            return nullptr;

        //1.一个是根节点,一个是子节点,返回根节点
        if(p == root || q == root)
            {
                return root;
            }
        //2.一个在左,一个在右
        //要判断p,q在左还是右,用一个bool 递归
       bool pLeft = IsInTree(root->left,p);
       bool pRight = !pLeft;  //这里判断一个子树就可以,右树取反
       bool qLeft = IsInTree(root->left,q);
       bool qRight = !qLeft;

       if(pLeft&&qRight || pRight&& qLeft)
            return root;
       else if(pLeft && qLeft )
            return lowestCommonAncestor (root->left,p,q);
       else if(pRight && qRight)
            return lowestCommonAncestor(root->right,p,q);

        return 0;
    }
};

5. 二叉树搜索树转换成排序双向链表

题目描述:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

将一个 二叉搜索树 就地转化为一个 已排序的双向循环链表

对于双向循环列表,你可以将左右孩子指针作为双向循环链表的前驱和后继指针,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。

特别地,我们希望可以 就地 完成转换操作。当转化完成以后,树中节点的左指针需要指向前驱,树中节点的右指针需要指向后继。还需要返回链表中最小元素的指针。

分析:

思路1:中序遍历,将节点放进vector中,再改链接关系(不符合空间复杂度O(1))

思路2:中序遍历这棵树,同时记录前驱节点prev,cur的左指针指向前驱。prev的右指针指向cur。这个思路的精华就是cur出现在不同的栈帧中prev只用了一个,所以使用的引用

class Solution {
public:
	void InorderConvert(TreeNode * cur,TreeNode *&prev)
	{
		if(cur == nullptr)
			return;
		InorderConvert(cur->left,prev);
		//这里cur出现的顺序就是中序
		cur->left = prev;
		if(prev)
			prev->right = cur;
		prev = cur;
		InorderConvert(cur->right,prev);
	}


    TreeNode* Convert(TreeNode* pRootOfTree) {
		TreeNode * prev = nullptr;
        InorderConvert(pRootOfTree,prev);

		//找到最左的节点就是头
		TreeNode * head = pRootOfTree;
		while(head && head->left)
		{
			head = head->left;
		}

		return head;
    }
};

6. 根据一棵树的前序遍历与中序遍历构造二叉树

给定两个整数数组 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]

分析:前序的顺序是根,左,右。通过前序可以确定出根节点

           中序的顺序是左,根,右。根据中序可以确定出左右子区间

class Solution {
public:
      TreeNode* _buildTree(vector<int>& preorder, vector<int>& inorder , int & prei,int inbegin, int inend) {
          if(inbegin >inend)
            return nullptr;
          TreeNode * root = new TreeNode(preorder[prei]);
          //分割出左右子区间 在中序里面找根
            int rooti = inbegin;
            while(rooti <= inend)
            {
                if(inorder[rooti] == preorder[prei])
                    break;
                else
                    rooti++;
            }
            //[inbegin rooti-1] rooti [rooti+1 inend] 
            ++prei;
          root->left = _buildTree(preorder,inorder,prei,inbegin,rooti-1);
          root->right = _buildTree(preorder,inorder,prei,rooti+1,inend);
          return root;

      }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        int i = 0;
      
       return _buildTree(preorder,inorder,i,0,inorder.size()-1);


    }
};

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

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

相关文章

C语言分支结构程序之if语句(1)

目录 if语句其一 奇数的判定 if语句其二 对奇数偶数的判断 if语句的结构图 专题 语法结构 结构图的阅读方法 结构图示例 相等运算符 关系运算符 嵌套的if语句 if语句其一 大家的一天都会怎么度过呢&#xff1f;我想应该不会是被设计好的程序那样循规蹈矩&#xff0c;我们…

字符集——带你了解UTF-8的前世今生

文章目录 字符集的来历汉字和字母的编码特点Unicode字符集字符集小结编码和解码开发约定 字符集的来历 计算机是美国人发明的&#xff0c;由于计算机能够处理的数据只能是0和1组成的二进制数据&#xff0c;为了让计算机能够处理字符&#xff0c;于是美国人就把他们会用到的每一…

关于 Kubernetes中Admission Controllers(准入控制器) 认知的一些笔记

写在前面 工作中遇到&#xff0c;简单整理记忆博文为官方文档整理涉及内置准入控制的分类理解理解不足小伙伴帮忙指正 人活着就是为了忍受摧残&#xff0c;一直到死&#xff0c;想明了这一点&#xff0c;一切事情都能泰然处之 —— 王小波《黄金时代》 为什么需要准入控制器 准…

【Qt开发流程】之对象模型2:属性系统

描述 Qt提供了一个复杂的属性系统&#xff0c;类似于一些编译器供应商提供的属性系统。然而&#xff0c;作为一个独立于编译器和平台的库&#xff0c;Qt不依赖于非标准的编译器特性&#xff0c;如__property或[property]。 Qt解决方案适用于Qt支持的所有平台上的任何标准c编译…

高性能网络编程 - 白话TCP 三次握手过程

文章目录 概述TCP协议头的格式TCP Finite State Machine (FSM) 状态机三次握手如何在 Linux 系统中查看 TCP 状态 概述 每一个抽象层建立在低一层提供的服务上&#xff0c;并且为高一层提供服务。 我们需要知道 TCP在网络OSI的七层模型中的第四层——Transport层 -----------…

百度智能云正式上线Python SDK版本并全面开源

文章目录 前言一、SDK的优势二、千帆SDK&#xff1a;快速落地LLM应用三、如何快速上手千帆SDK3.1、SDK快速启动3.2. SDK进阶指引 3.3. 通过Langchain接入千帆SDK4、开源社区 前言 百度智能云千帆大模型平台再次升级&#xff01;在原有API基础上&#xff0c;百度智能云正式上线…

MicroPython标准库

MicroPython标准库 arraybinascii(二进制/ASCII转换)builtins – 内置函数和异常cmath – 复数的数学函数collections – 集合和容器类型errno – 系统错误代码gc – 控制垃圾收集器hashlib – 散列算法heapq – 堆队列算法io – 输入/输出流json – JSON 编码和解码math – 数…

周周爱学习之Redis重点总结

redis重点总结 在正常的业务流程中&#xff0c;用户发送请求&#xff0c;然后到缓存中查询数据。如果缓存中不存在数据的话&#xff0c;就会去数据库查询数据。数据库中有的话&#xff0c;就会更新缓存然后返回数据&#xff0c;数据库中也没有的话就会给用户返回一个空。 1.缓…

【6】PyQt信号和槽

1. 信号和槽简介 信号和槽机制是 QT 的核心机制&#xff0c;应用于对象之间的通信 信号和槽是用来在对象间传递数据的方法当一个特定事件发生的时候&#xff0c;signal会被emit出来&#xff0c;slot调用是用来响应相应的signal的Qt中对象已经包含了许多预定义的 signal&#…

全网最新最全的Appium自动化:使用appium后安卓手机无法调出键盘解决方法

问题&#xff1a;用appium进行真机调试后&#xff0c;使用手机的app进行输入时无法调出键盘。 原因&#xff1a;appium调试时&#xff0c;将手机输入法设置成了Unicode IME 注&#xff1a;按键详细操作参考&#xff1a;转载至 作者&#xff1a;oscarforever 地址&#xff1…

Java链接数据库

本文介绍的是Java链接数据库中的JDBC操作&#xff0c;JDBC虽然现在用的不多&#xff0c;但面试的时候会问道。需要有相应的了解。下面以链接MySQL为例子。 JDBC 什么jdbc Java DataBase Connectivity是一种用于执行SQL语句的Java API&#xff0c;它由一组用Java语言编写的类和…

制作一个RISC-V的操作系统五-RISC-V汇编语言编程一

文章目录 RISC-V汇编语言入门汇编语言概念简介 汇编语言语法介绍&#xff08;GNU版本&#xff09; RISC-V汇编语言入门 汇编语言概念简介 高级&#xff1a;可以理解就是更贴近人的理解 低级&#xff1a;可以理解就是更贴近机器的 难移植&#xff1a;汇编指令基本上和机器指令…

对标Gen-2!Meta发布新模型,进军文生视频赛道

随着扩散模型的飞速发展&#xff0c;诞生了Midjourney、DALLE 3、Stable Difusion等一大批出色的文生图模型。但在文生视频领域却进步缓慢&#xff0c;因为文生视频多数采用逐帧生成的方式,这类自回归方法运算效率低下、成本高。 即便使用先生成关键帧,再生成中间帧新方法。如…

网络模拟与网络仿真

目录 一、概念界定 二、模拟&#xff08;simulation&#xff09;与仿真&#xff08;emulation&#xff09; 2.1 模拟&#xff08;simulation&#xff09; 2.2 仿真&#xff08;emulation&#xff09; 2.3 区分 三、网络模拟与网络仿真 3.1 网络模拟 3.2 网络仿真 3.…

软件测试要学习的基础知识——黑盒测试

黑盒测试概述 黑盒测试也叫功能测试&#xff0c;通过测试来检测每个功能是否都能正常使用。在测试中&#xff0c;把程序看作是一个不能打开的黑盒子&#xff0c;在完全不考虑程序内部结构和内部特性的情况下&#xff0c;对程序接口进行测试&#xff0c;只检查程序功能是否按照…

解析 Smilee Finance:基于无偿损失的链上期权方案

“有了 Smilee Finance&#xff0c;无偿损失或许不再是一种损失&#xff0c;它也更可能是一种可组合性的收益” 无偿损失 流动性挖矿是引燃 DeFi Summer 的导火索&#xff0c;在 AMM DEX 中&#xff0c;它允许用户将资产按照比例添加到 AMM 流动性池中成为 LP&#xff0c;以为交…

POJ 3233 Matrix Power Series 动态规划(矩阵的幂)

一、题目大意 给出一个矩阵A&#xff0c; 输出矩阵B的每一项对M取余数的值。 二、解题思路 以二维矩阵为例&#xff0c;首先计算K2的情况&#xff0c;我们设结果矩阵为B 有如下表达式 那么不难看出&#xff0c;需要的矩阵其实就是以下的两个矩阵相乘后的左上角的N*N个 然后…

RoPE旋转位置编码浅析

RoPE旋转位置编码浅析 本文介绍了旋转位置编码RoPE在大模型中的广泛应用,包括Llama、Mistral 7B、Baichuan、ChatGLM、Qwen、…等。由于计算资源限制,大模型通常在较小的上下文长度中进行训练,导致在推理超出预训练长度时性能显著下降。为了解决这个问题,涌现了许多基于Ro…

火山引擎DataTester升级MAB功能,助力企业营销决策

更多技术交流、求职机会&#xff0c;欢迎关注字节跳动数据平台微信公众号&#xff0c;回复【1】进入官方交流群 DataTester&#xff0c;火山引擎推出的 AB 测试与智能优化平台&#xff0c;近日宣布对其 MAB&#xff08;Multi-armed Bandit&#xff09;功能进行了升级&#xff0…

如果不小心修改了按钮的名字并且忘记了原名字

出现上述情况&#xff0c;可以右边点击转到代码&#xff0c;注释掉问题行&#xff0c;此页的设计界面就恢复了。
最新文章