二叉树题型

news2024/11/18 5:51:01

目录

二叉数遍历迭代法

1.1前序遍历

1.2中序遍历

1.3后续遍历

二叉树最小深度

二叉树所有路径

中序后序构造二叉树

验证二叉搜素树



二叉数遍历迭代法

1.1前序遍历

前序遍历顺序:根—左—右;

解法1:用栈来进行中间过程处理,结果存入vector中

思路:每次先处理中间的结点,先将根结点入栈,再将右孩子入栈,左孩子入栈。每次从栈顶拿数据,重复操作。

 代码演示:

class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) return result;
        st.push(root);
        while (!st.empty()) 
       {
            TreeNode* node = st.top();                      
            st.pop();
            result.push_back(node->val);
            if (node->right) st.push(node->right);          
            if (node->left) st.push(node->left);                  
       }
        return result;
    }
};

 解法2:中序遍历是先访问根结点,然后访问左子树。

我们可以直接把先访问的根结点直接存入vector中,然后去遍历它的左子树。重复上一次操作。当它的左子树为空时,则去遍历它的右子树。(右子树也按之前的方法,不为空则直接放入vector中,后去遍历它的左子树)  其中要把遍历过的结点放入栈中,当它的左子树为空时,栈顶元素就是该子树的根结点,可通过它去找到右子树,若其右子树也为空,也一样可以通过栈顶元素去找右子树。(访问栈顶元素后要将其出栈)

 代码演示:


class Solution {
public:
    vector<int> preorderTraversal(TreeNode* root) {
        stack<TreeNode*> s;
        vector<int> v;
        TreeNode*cur=root;
        while(cur||!s.empty())
        {
            while(cur)
            {
                s.push(cur);
                v.push_back(cur->val);
                cur=cur->left;
            }
            TreeNode* top=s.top();
            s.pop();
            cur=top->right;
        }
        return v;
    }
};

1.2中序遍历

中序遍历顺序:左—根—右

思路:与上面前序遍历的解法2类似,但由于访问左子树先于根结点,所以访问左子树时只需把其入栈,不用放入vector中,当其左子树为空时,那么此时栈中最后的元素可当作左结点,将其放入vector中,后通过栈顶元素找到其右子树,(把栈顶元素出栈),以同样的方法去遍历右子树。

代码实现:

class Solution {
public:
    vector<int> inorderTraversal(TreeNode* root) {
        vector<int> v;
        stack<TreeNode*> s;
        TreeNode*cur=root;
        while(cur||!s.empty())
        {
            while(cur)
            {
                s.push(cur);
                cur=cur->left;
            }
            TreeNode* top=s.top();//其左子树为空
            s.pop();
            v.push_back(top->val);
            cur=top->right;        //去找右子树,以同样方法遍历右子树
        }
        return v;
    }
};

1.3后续遍历

后续遍历顺序:左—右—根

解法1:与前序遍历解法一类似,只要把入栈顺序更改下,再将放入vector中的数据反转一下即可。

代码实现:

class Solution {
public:
    vector<int> postorderTraversal(TreeNode* root) {
        stack<TreeNode*> st;
        vector<int> result;
        if (root == NULL) 
           return result;
        st.push(root);
        while (!st.empty()) {
            TreeNode* node = st.top();
            st.pop();
            result.push_back(node->val);
            if (node->left) st.push(node->left); 
            if (node->right) st.push(node->right); 
        }
        reverse(result.begin(), result.end()); 
        return result;
    }
};

解法2:

与中序遍历解法类似,不过后序遍历的访问顺序是右子树先于根结点。

当cur一直往后遍历时,当其左子树为空时,此时栈中最后一个元素当成是根结点,此时有两种情况。

1.那个根结点的右子树为空,那么将根结点当成子树的左孩子,将其放入vector中,并将其出栈。

2.那个根结点此时右子树不为空,则以同样的方法遍历该根结点的右孩子。当遍历完返回后,回到这个根结点时,又会去遍历它的右子树,所以需要记录该根结点的右子树(不为空时)是否被访问过。

代码实现:

 vector<int> postorderTraversal(TreeNode* root) {
        vector<int> v;
        stack<TreeNode*> s;
        TreeNode*cur=root;
        TreeNode* pre;
        while(cur||!s.empty())
        {
            while(cur)
            {
                s.push(cur);
                cur=cur->left;
            }
            TreeNode* top=s.top();
            if(top->right==nullptr||top->right==pre)//右子树为空或则已近访问过了
            {
                v.push_back(top->val);
                s.pop();
                pre=top;
            }
            else
            {
                cur=top->right;
            }
        }
        return v;

    }

二叉树最小深度

最小深度是指根节点到最近叶子节点的最短路径上的节点数量

题目描述

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==nullptr)
         return 0;
    int lefti=minDepth(root->left);
    int righti=minDepth(root->right);
    if(root->left==nullptr&&root->right!=nullptr)
        lefti=righti;
    if(root->right==nullptr&&root->left!=nullptr)
       righti=lefti;
    
    return 1+min(lefti,righti);

    }
};

迭代:

class Solution {
public:
    int minDepth(TreeNode* root) {
        if(root==nullptr)
         return 0;
        queue<TreeNode*> _q;
        _q.push(root);
        int count=0;
        while(!_q.empty())
        {
            int size=_q.size();
            count++;
            int flag=0;
            while(size--)
            {
                TreeNode* cur=_q.front();
                _q.pop();
                if(cur->left==nullptr&&cur->right==nullptr)
               {
                  return count;
               }
                if(cur->left!=nullptr)
                 _q.push(cur->left);
                if(cur->right!=nullptr)
                 _q.push(cur->right);
            }
          
        }
        return count;
    }
};

二叉树所有路径

题目描述

代码:解法1

深度优先搜索

如果当前节点不是叶子节点,则在当前的路径末尾添加该节点,并继续递归遍历该节点的每一个孩子节点。
如果当前节点是叶子节点,则在当前路径末尾添加该节点后我们就得到了一条从根节点到叶子节点的路径,将该路径加入到答案即可。

class Solution {
public:

void _binary(string s,vector<string>& v,TreeNode* root)
{
    if(root!=nullptr)
     s+=to_string(root->val);
    if(root->left==nullptr&&root->right==nullptr)
    {
         v.push_back(s);
         return;
    }
      if(root->left)
          _binary(s+"->",v,root->left);
      if(root->right)
         _binary(s+"->",v,root->right);
}
    vector<string> binaryTreePaths(TreeNode* root) {
        string str;
        vector<string> v;
        _binary(str,v,root);
        return v;
    }
};

解法2:与解法1类似,用广度优先搜索来实现。不过用到了队列来辅助,来记录遍历的节点。其中结点值与->是成对出现的。  pair<TreeNode*,string> p(root,"")一起进行出入队列操作。每一个结点值有它对应的路劲,

class Solution {
public:
       vector<string> binaryTreePaths(TreeNode* root) {
        vector<string> v;
        queue< pair<TreeNode*,string> > q;
        pair<TreeNode*,string> p(root,"");
        q.push(p);  
        while(!q.empty())
        {   
            string path = q.front().second ;
            root = q.front().first;
            q.pop();
            path += to_string(root->val);
            if(!root->left && !root->right)
            {
                v.push_back(path);
                continue;
            }
            path += "->";
            if(root->left)
            {
                p = {root->left,path};
                q.push(p);
            }    
            if(root->right)
            { 
                p = {root->right,path};
                q.push(p);
            }
        }
        return v;
    }
};

相关题型:力扣112,113

中序后序构造二叉树

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

通过postorder数组最后面的元素,可以找到根结点,后面在inorder 数组里面找到该元素,在中序遍历的数组里,该元素前面的就是它的左子树,后面的是它的右子树。先找它的右子树,因为在inorder 数组里面元素顺序是左-右-根,离根结点近的是右子树。

代码: 

class Solution {
public:
    TreeNode* _bulidTree(vector<int>& inorder, vector<int>& postorder,
        int& pre, int begin, int end)
    {
        if (begin > end)
            return nullptr;
        TreeNode* root = new TreeNode(postorder[pre]);
        pre--;
        int rooti = begin;
        while (rooti <= end)
        {
            if (root->val == inorder[rooti])
                break;
            else
                rooti++;
        }

        root->right = _bulidTree(inorder, postorder, pre, rooti + 1, end);
        root->left = _bulidTree(inorder, postorder, pre, begin, rooti - 1);
        return root;

    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        int begin, end, pre;
        begin = 0;
        end = pre = postorder.size() - 1;
        return _bulidTree(inorder, postorder, pre, begin, end);

    }
};

相关题型:105

验证二叉搜素树

给你一个二叉树的根节点 root ,判断其是否是一个有效的二叉搜索树。

解法1:根据二叉搜书树的性质,对其进行后续遍历,若是二叉搜索树,则后续遍历的结果是完全升序的。

解法2:与上面介绍的后序遍历第二种思路相似,要用一个变量去记录之上一个结点。

class Solution {
public:
    bool isValidBST(TreeNode* root) {
        stack<TreeNode*> st;
        TreeNode* cur = root;
        TreeNode* pre = NULL; // 记录前一个节点
        while (cur != NULL || !st.empty()) {
            while (cur)
            {
                st.push(cur);
                cur = cur->left;                // 左
            }
            cur = st.top();                     // 中
            st.pop();
            if (pre != NULL && cur->val <= pre->val)
                return false;
            pre = cur; //保存前一个访问的结点
            cur = cur->right;                  // 右
        }
        return true;
    }
};

相关题型:力扣530

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

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

相关文章

Babel和devServer | Webpack

文章目录Babel和devServerbabelbabel命令行使用babel-loaderVue源码的打包VSCode对SFC文件的支持vue-loaderdevServerBabel和devServer babel babel命令行使用 babel-loader Vue源码的打包 VSCode对SFC文件的支持 vue-loader devServer

一键可以轻松替换人物背景图,效果出乎意料的好(附 Python 代码)

最近发现 BackgroundMattingV2 项目的一些使用上的小缺陷&#xff0c;但是他却可以做到头发丝精细的抠图效果。我将项目稍微魔改了一下&#xff0c;让他在可以选择单一图片的基础上&#xff0c;可以把抠好的图片贴在自定义的背景图上&#xff0c;这样就可以让照片中的人物&…

使用Tomcat时出现Access Error: 404 -- Not Found的解决办法

当时出现这种情况很迷惑&#xff0c;错误提示如下 突然想到大二上学模电的时候安装过multisim&#xff0c;这个软件的某些不必要的服务占用了8080端口&#xff08;恼&#xff09;&#xff0c;出现这种情况应该是和Tomcat默认的端口冲突了。 于是就有了解决思路&#xff1a; …

stm32f407VET6 系统学习 day03 通用同步异步收发器

1.同步串行通信 同步通信发送端和接收端必须用共同的时钟源才能保持它们之间的准确同步。同步传输时&#xff0c;每个字 符没有起始位和停止位&#xff0c;它不是用起始位来标志字符的开始&#xff0c;而是用一串特定的二进制序列&#xff0c;称为 同步字符&#xff0c;去通知接…

[思维模式-14]:《复盘》-2- “知”篇 - 复盘之道

目录 前言&#xff1a; 一、U型学习法&#xff1a;复盘的学习机理 &#xff08;1&#xff09; 回顾、评估 &#xff08;2&#xff09;分析、反思 &#xff08;3&#xff09;萃取、提炼 &#xff08;4&#xff09;转化、应用 二、复盘与PDCA既有区别&#xff0c;也有联系…

solr 安装和使用

Solr是基于ApacheLucene构建的流行、快速、开源的企业搜索平台 Solr具有高度可靠性、可扩展性和容错性&#xff0c;提供分布式索引、复制和负载平衡查询、自动故障切换和恢复、集中配置等功能。Solr为许多世界上最大的互联网站点提供搜索和导航功能 环境准备 linux centos7 ja…

如何用iDesktop快速制作一幅研究区概况图

目录前言数据准备成果展示制作步骤前言 研究区概况图能直观展示研究区域的地理位置&#xff0c;在许多研究展示与论文撰写中必不可少。本文将以成都市为例&#xff0c;利用SuperMap桌面产品iDesktop快速制作一幅研究区概况图。 数据准备 四川省行政区划矢量数据&#xff08;…

【语音处理】LQ/QR噪声估计器研究(Matlab代码实现)

&#x1f468;‍&#x1f393;个人主页&#xff1a;研学社的博客 &#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜…

【Javascript】循环,函数,调用栈,闭包,递归

❤️ Author&#xff1a; 老九 ☕️ 个人博客&#xff1a;老九的CSDN博客 &#x1f64f; 个人名言&#xff1a;不可控之事 乐观面对 &#x1f60d; 系列专栏&#xff1a; 文章目录函数作用域例子调用栈可选参数闭包递归函数 形参不需要定义var&#xff0c;函数可以付给一个变量…

Android Qcom USB Driver学习(八)

该系列文章总目录链接与各部分简介&#xff1a; Android Qcom USB Driver学习(零) 因为要看usb charging的问题&#xff0c;所以需要补充一下battery的相关知识&#xff0c;算是入门吧 BAT SCH (1)VBATT_VSNS_P (2)BAT_THERM (3)I2C_SDA (4)I2C_SCL (5)VBATT_VSNS_M (1)BATT…

【问题分析】解决java中epoll依赖缺失问题

【问题分析】解决java中epoll依赖缺失问题一、前言二、问题描述三、问题分析四、解决方法五、总结一、前言 在学习使用lettuce框架实现UNIX域套接字unix domain socket连接redis时&#xff0c;遇到了一个问题&#xff0c;提示java.lang.IllegalStateException: A unix domain …

Java Stream后续来了,汇总一些项目开发中高频使用的 Stream操作

不过讲解这些操作时用的都是非常简单的例子&#xff0c;流操作的数据也都是简单类型的&#xff0c;主要的目的是让大家能更快速地理解 Stream 的各种操作应用在数据上后&#xff0c;都有什么效果。 在现实场景中实际做项目的时候&#xff0c;我们使用Stream操作的数据大多数情…

OpenCV颜色识别

颜色分辨 单个颜色识别 代码 import cv2 import numpy as npdef color(lower, upper, name):Img cv2.imread(image/origin/all.png) # 读入一幅图像kernel_3 np.ones((3, 3), np.uint8) # 3x3的卷积核if Img is not None: # 判断图片是否读入HSV cv2.cvtColor(Img, cv2…

maven中profiles使用详解,多环境开发配置文件(开发,测试,生产)+ pom中resources部分标签介绍

一.maven中profiles使用详解&#xff08;仅供参考&#xff09; 使用的场景 常常遇到一些项目中多环境切换的问题。比如在开发过程中用到开发环境&#xff0c;在测试中使用测试环境&#xff0c;在生产中用生产环境的情况。springboot中提供了 spring.profile.active的方式来实…

以mariadb为例介绍如何使用systemctl命令集设置服务开机自启动

以mariadb为例介绍如何使用systemctl命令集设置服务开机自启动一、systemd简介二、systemctl命令集常用命令三、以mariadb自启动为例四、更多说明一、systemd简介 systemd即为system daemon,是linux下的一种init软件,由Lennart Poettering带头开发,并在LGPL 2.1及其后续版本许…

[思维模式-13]:《复盘》-1- “知”篇 - 认识复盘

目录 前言 一、什么是复盘 二、复盘的三个关键词 三、复盘&#xff0c;而非总结 四、复盘的优势与局限 五、复盘与行动学习、培训、绩效改进的区别与联系 六、关于复盘的几个常见误解 误解1&#xff1a;可否对他人之事进行复盘 误解2&#xff1a;“项目后评估”是复盘吗…

细粒度图像分类模型(含实战代码)

来源&#xff1a;投稿 作者&#xff1a;lsc 编辑&#xff1a;学姐 理论部分 01细粒度图片分类问题 1.1细粒度图片分类特点 可判别区域往往只是在图像中很小的一块区域内。 1.2细粒度图像分类数据集 1.3细粒度图像分类竞赛 1.4细粒度图像分类模型分类: (1)强监督模型: 需要…

Java之AQS

AQS是什么 是用来实现锁或者其它同步器组件的公共基础部分的抽象实现&#xff0c;整体就是一个抽象的FIFO队列来完成资源获取线程的安排工作&#xff0c;并通过一个int类变量表示持有锁的状态。 使用到AQS的一些类 ReentranLock: CountDownLatch ReentrantReadWriteLock:…

Go语言开发小技巧易错点100例(四)

往期回顾&#xff1a; Go语言开发小技巧&易错点100例&#xff08;一&#xff09;Go语言开发小技巧&易错点100例&#xff08;二&#xff09;Go语言开发小技巧&易错点100例&#xff08;三&#xff09; 本期看点&#xff08;技巧类用【技】表示&#xff0c;易错点用…

_14LeetCode代码随想录算法训练营第十四天-C++二叉树

_14LeetCode代码随想录算法训练营第十四天-C二叉树 题目列表 104.二叉树的最大深度559.n叉树的最大深度111.二叉树的最小深度222.完全二叉树的节点个数 104.二叉树的最大深度 题目 给定一个二叉树&#xff0c;找出其最大深度。 二叉树的深度为根节点到最远叶子节点的最长…