力扣二叉树题解含思路(C++实现)

1.求二叉树的最近公共祖先:

        原题链接:. - 力扣(LeetCode)

        假设这题的p,q分别为7和8,而它们的最近公共祖先肯定是为3。

这题我们大致的思路为保存p,q的绝对路径,接着通过存储的绝对路径去寻找第一个相同的节点假设公共节点。

        1.1:寻找7节点:

        

                1.2:8节点也是同样的方式进行:

        1.3:找到最近的公共节点

                

        代码:

class Solution {
public:
    bool Find(TreeNode* root,TreeNode* val,stack<TreeNode*>&st)
    {
        if(!root)
            return false;
        st.push(root);
        if(root==val)
            return true;

        if(Find(root->left,val,st))
            return true;
        if(Find(root->right,val,st))
            return true;

        //如果此时的节点的根,左子树,右子树都没有找到val,就说明val并不在这个节点,将这个节点pop掉。
        st.pop();
        return false;        
    }


    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
    {
        //1.使用两个栈用来保存p,q的绝对路径
        //2.接着pop较长的栈,保持两个栈相等
        //3.两个栈同时pop,最终得到相等的就是祖先
        stack<TreeNode*> st1;
        stack<TreeNode*> st2;
        Find(root,p,st1);
        Find(root,q,st2);

        while(st1.size()>st2.size())
            st1.pop();

        while(st2.size()>st1.size())
            st2.pop();
            
        while(st1.top()!=st2.top())
        {
            st1.pop();
            st2.pop();
        }
        return st1.top();
    }
};

2.二叉搜索树与双向链表

        原题链接:二叉搜索树与双向链表_牛客题霸_牛客网

        其实这题如果忽略题目要求就很简单,因为是标准的搜索二叉树,就通过中序遍历存入list题目就解决了,但小编应题目要求,空间复杂度为O(1)及在原树上操作。本题需要对递归有一定的理解才方便做。

        

        这里小编要提出一个穿越者思想,及把自己想象成一个可以穿越时间的人,而二叉树有left和right与根。将left想象成昨天,将right想象成明天。因为是搜索二叉树所以必然会走一个中序遍历,所以我们将在中序遍历上进行操作。

        条件1:我们知道昨天发生什么

        条件2:我们虽然不知道明天将发生什么,但我们穿越到明天后再回到今天就能知道明天发生什么。

        

        这里小编想多一嘴,为什么cur会回到6节点,因为我们采用的方式是递归,递归函数会进行压栈,当我们压入4节点的函数栈帧时候,6节点栈帧会保存在4节点下面,而当4节点函数结束时候,此时函数栈帧进行弹出销毁,6节点就是栈顶,所以此时cur的值就是6.而且因为递归的关系,就算指向改变了也不会影响中序遍历的顺序,因为已经将顺序全部压入栈中了。

                

        代码:

class Solution {
public:
	bool TrainsTree(TreeNode*&prev,TreeNode*cur)
	{
		if(cur==nullptr)
			return false;
		TrainsTree(prev,cur->left);
		
		cur->left=prev;
		if(prev)
			prev->right=cur;
		prev=cur;
		TrainsTree(prev, cur->right);
		return true;
	}

    TreeNode* Convert(TreeNode* pRootOfTree)
	{
        TreeNode*prev=nullptr;
		TrainsTree(prev, pRootOfTree);
		TreeNode*head=pRootOfTree;
		while (head&&head->left) {
			head=head->left;
		}
		return  head;
    }
};

       代码看着很简单,就只是在改动指针之间的指向,但这就是递归的魅力,看着很简单,实际想出来很难。

3.从前序和中序遍历序列构建二叉树

        原题链接:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

        

        题目要求给定两个二叉树序列的数组,要求我们从两个序列中构建二叉树,那么我们先从画图思考如何构建。  

        代码:

class Solution {
public:
    TreeNode*_build(vector<int>& preorder, vector<int>& inorder,
                    int &pi,int ileft ,int iright )
    {
       if(ileft>iright)
            return nullptr;
       
        //使用前序遍历思想,进来就先确定根
        TreeNode *key=new TreeNode(preorder[pi]);
        
        //使用中序遍历思想,找到根,区分根的左子树与右子树
        int keyi=0;
        while(keyi<inorder.size())
        {
            if(inorder[keyi]==preorder[pi])
                break;
            keyi++;
        }

        pi++;

        //[ileft keyi-1] keyi [keyi+1 iright];
        key->left=_build(preorder,inorder,pi,ileft,keyi-1);
        key->right=_build(preorder,inorder,pi,keyi+1,iright);
        return key;
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder)
    {
        int pi=0, ileft=0 , iright=inorder.size()-1;
        return _build(preorder,inorder,pi,ileft,iright);
    }
};

        代码递归结束条件为ileft大于iright,就好比如我们想确定9是不是属于叶子节点,在递归9的左子树时,ileft=0,iright=-1,而在递归9的右子树时候会发现ileft=1,而iright=0。这显然不是一个有效的区间所以直接退出。

4.二叉树的前序遍历

        原题链接:144. 二叉树的前序遍历 - 力扣(LeetCode)

        可能看到这有读者疑惑,这题不是很简单吗,为啥还需要拿出来讲。是的这题使用递归的思想就是很简单,但如果要求采用的是非递归的方式呢?应该怎么做

        

        

        假设我们需要前序遍历这颗子树应该怎么遍历呢?

        

        因为是前序遍历,所以我们在一开始遍历根的时候直接将值存入vector中,在将节点压入栈中。

        这里主要的核心是通过栈的先进先出的特性来模拟递归遍历的过程,当我们的cur指针只需要一直往左子树遍历。用栈去存储节点,当cur指向空的时候表明该根的左子树已经遍历完成,接着弹出栈顶节点,如果栈顶节点没有右节点就不用管,继续弹出下一个栈顶节点,而如果弹出的栈顶节点有右子树,那么我们就重新让cur指向我们弹出节点的右节点,接着继续遍历入栈循环。直到栈为空与cur指向为空,就表明该子树全部遍历完成了。

        代码:

    vector<int> preorderTraversal(TreeNode* root)
    {
        vector<int> vv;
        stack<TreeNode*> st;
        TreeNode *cur=root;
        TreeNode *temp=nullptr;
        while(cur||!st.empty())
        {
            if(cur)
            {
                vv.push_back(cur->val);
                st.push(cur);
                cur=cur->left;
            }
            else
            {
                temp= st.top();
                st.pop();
                cur=temp->right;  
            }
        }
        return vv;
    }

        

5.二叉树的后序遍历

        原题链接:145. 二叉树的后序遍历 - 力扣(LeetCode)

        这题我们就以这颗二叉树为例,我们直到后序遍历为:左子树|右子树|根 而很显然在后序遍历的时候根节点会被访问两次,所以这题我们会两次访问根节点,而难点在于我们并不知道我们的右子树是否已经访问过了.

                

        代码:

 vector<int> postorderTraversal(TreeNode* root)
    {
        vector<int> vv;
        stack<TreeNode*> st;
        TreeNode *cur=root;
        TreeNode *temp=nullptr;
        TreeNode*prev=nullptr;
        while(cur||!st.empty())
        {
            while(cur)
            {
                st.push(cur);
                cur=cur->left;
            }

            //后序遍历二叉树会走两次根节点,
            //如果一个根的右节点没被访问,那么访问根的前一个节点为根的左子树
            //如果一个根的右子树被访问了,那么访问根的前一个节点为根的右子树
            temp=st.top();
            if(temp->right==nullptr || prev==temp->right)
            {
                vv.push_back(temp->val);
                st.pop();
                prev=temp;
                
            }else
            {
                cur=temp->right;
            }
        }
        return vv;
    }

                                

                                                                                                那么本片文章到这里就结束了,感谢各位观看,如果觉得对您有帮助,还请点点赞

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

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

相关文章

K8S资源介绍之configmap

1 configmap介绍 是什么&#xff1a;是K8S内置的一种存储卷&#xff0c;数据存储在etcd数据库中 应用场景&#xff1a;主要是存储应用的配置&#xff0c;实现配置与应分离&#xff0c;可以实现类似配置配置中心的功能 由于镜像是只读的特性&#xff0c;如果想要修改需要重新…

数据结构与算法学习——背包问题总结

主要学习01背包和完全背包。 01 背包 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i]&#xff0c;得到的价值是value[i] 。每件物品只能用一次&#xff0c;求解将哪些物品装入背包里物品价值总和最大。 装满问题 二维&#xff1a; 一维&#xff1a; 组…

算法分析中的渐进符号

在算法分析中,渐进符号用于描述算法在输入规模趋于无穷大时的运行时间或空间增长速率。主要的渐进符号包括 O O O、 Ω \Omega Ω、 Θ \Theta Θ、 o o o 和 ω \omega ω。这些符号各自描述了不同的增长界限,本文给出详细的定义和区别。 渐进符号 1. 大 O O O 符号(B…

计算机毕业设计Python+大模型农产品价格预测 ARIMA自回归模型 农产品可视化 农产品爬虫 机器学习 深度学习 大数据毕业设计 Django Flask

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

sql专题 之 三大范式

文章目录 背景范式介绍第一范式&#xff1a;属性不可再分第二范式第三范式注意事项 为什么不遵循后续的范式数据库范式在实际应用中会遇到哪些挑战&#xff1f; 背景 数据库的范式&#xff08;Normal Form&#xff09;是一组规则&#xff0c;用于设计数据库表结构以 减少数据冗…

Linux下进程链接结构,命令行参数,环境变量

bash 是一种 shell。在 Linux 系统中&#xff0c;当我们在终端输入命令时&#xff0c;通常是在一个 shell 环境下进行的。如果这个 shell 是 bash&#xff0c;那么所有命令行执行的命令都是 bash 的子进程。 1.Linux下进程链接结构 进程链接补充知识&#xff1a; 所有进程都…

FPGA实现串口升级及MultiBoot(八)四样错误实例演示

本文目录索引 一个指令和三种方式二种位流和四样错误Golden位流工程Watchdog的原理1、打开自己使用的Vivado版本的TCL SHELL2、进入multiboot_address_table.tcl 文件所在目录3、运行 multiboot_address_table.tcl 文件4、按照需求输入参数启动地址确定MultiBoot位流工程验证ex…

信息安全工程师(84)UNIX/Linux操作系统安全分析与防护

前言 UNIX/Linux操作系统&#xff0c;尤其是Linux&#xff0c;以其开放性、稳定性和安全性在服务器、桌面、嵌入式设备和超级计算机中占据重要地位。然而&#xff0c;没有任何操作系统可以百分之百地保证安全&#xff0c;UNIX/Linux也不例外。 一、UNIX/Linux操作系统安全分析 …

day08(单片机)时钟系统+定时器+PWM

目录 时钟系统定时器PWM 时钟系统 时钟基本概念 时钟源 晶体振荡器&#xff08;Crystal Oscillator&#xff09; RC振荡器&#xff08;Resistor-Capacitor Oscillator&#xff09; ​​​​​​​STM32U5时钟源 HSI(High Speed Internal) HSE(High Speed External) LSI(Low Spe…

【JavaEE初阶 — 多线程】内存可见性问题 volatile

1. 内存可见性问题 内存可见性的概念 什么是内存可见性问题呢&#xff1f; 当一个线程对共享变量进行了修改&#xff0c;那么另外的线程都是立即可以看到修改后的最新值。在Java中&#xff0c;可以借助 synchronized、volatile 以及各种Lock 实现可见性。如果我们将变量声…

通用特效Shader

一、通用特效Shader介绍 1.1 什么是通用特效材质 Unity支持SRP Batcher后&#xff0c;使用UberShader的优势非常明显。所谓&#xff0c;UberShader&#xff0c;即一个超级Shader&#xff0c;覆盖一类功能&#xff0c;而不是多个分散的小Shader&#xff0c;比如一个通用特效Sh…

spark-本地模式的配置和简单使用

python环境的安装 在虚拟机中&#xff0c;只能安装一个python的版本&#xff0c;若想要安装别的版本&#xff0c;则需要卸载之前的版本——解决方式&#xff0c;安装Anaconda 通过百度网盘分享的文件&#xff1a;Anaconda3-2021.05-Linux-x86_64.sh 链接&#xff1a;https://…

分享三个python爬虫案例

一、爬取豆瓣电影排行榜Top250存储到Excel文件 近年来&#xff0c;Python在数据爬取和处理方面的应用越来越广泛。本文将介绍一个基于Python的爬虫程序&#xff0c;用于抓取豆瓣电影Top250的相关信息&#xff0c;并将其保存为Excel文件。 获取网页数据的函数&#xff0c;包括以…

PyQt5 详细安装与配置教程及使用

文章目录 Part1&#xff1a;安装 PyQt5Part2&#xff1a;配置 PyQt5 的依赖工具 QtDesigner 和 PyUICPart3&#xff1a;使用QtDesigner设计界面Part4&#xff1a;使用PyUIC将设计好的界面转换为.py文件Part5&#xff1a;通过代码显示ui界面 Part1&#xff1a;安装 PyQt5 需要安…

ssm079基于SSM框架云趣科技客户管理系统+jsp(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;客户管理系统设计与实现 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本客户管理系统就是在这…

C语言 | Leetcode C语言题解之第556题下一个更大元素III

题目&#xff1a; 题解&#xff1a; int nextGreaterElement(int n){int x n, cnt 1;for (; x > 10 && x / 10 % 10 > x % 10; x / 10) {cnt;}x / 10;if (x 0) {return -1;}int targetDigit x % 10;int x2 n, cnt2 0;for (; x2 % 10 < targetDigit; x2…

华为大变革?仓颉编程语言会代替ArkTS吗?

在华为鸿蒙生态系统中&#xff0c;编程语言的选择一直是开发者关注的焦点。近期&#xff0c;华为推出了自研的通用编程语言——仓颉编程语言&#xff0c;这引发了关于仓颉是否会取代ArkTS的讨论。本文将从多个角度分析这两种语言的特点、应用场景及未来趋势&#xff0c;探讨仓颉…

Linux:基本开发工具

一&#xff1a;编辑器vim 1.1vim的基本概念 vim其实有多重模式&#xff0c;这里我们主要了解vim的三种模式&#xff0c;分别是命令模式&#xff08;command mode&#xff09;,插入模式(Insert mode)和底行模式(lst line mode) 正常/普通/命令模式(Normal mode) …

第14张 GROUP BY 分组

一、分组功能介绍 使用group by关键字通过某个字段进行分组&#xff0c;对分完组的数据分别 “SELECT 聚合函数”查询结果。 1.1 语法 SELECT column, group_function(column) FROM table [WHERE condition] [GROUP BY group_by_expression] [ORDER BY column]; 明确&#…

TVM计算图分割--BYOC框架

文章目录 BYOC架构算子标注单算子标注复合算子标注Cost-based PartitionCodegenCodegen for C代码生成流程概览代码生成工程实现实现CodegenC实现CSourceCodegenCodegen for JSON实现JsonCodegenRuntimeJSONRuntime参考随着后端设备数量激增,为达到较高的效果在这些设备上,对…