leetcode 94二叉树的中序遍历
递归算法C++代码:
- /**
- * Definition for a binary tree node.
- * struct TreeNode {
- * int val;
- * TreeNode *left;
- * TreeNode *right;
- * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
- * };
- */
- class Solution {
- public:
- vector<int> inorderTraversal(TreeNode* root) {
- vector<int> tra;
- Morder(root,tra);
- return tra;
- }
- void Morder(TreeNode* root,vector<int> &tra){
- if(root==NULL) return;
- if(root->left)
- Morder(root->left,tra);
- tra.push_back(root->val);
- if(root->right)
- Morder(root->right,tra);
- }
- };
非递归方法(迭代):通过stack容器
C++代码:O(n)空间复杂度,O(n)时间复杂度
自己写的,实际上为将递归方法代码用stack具体化,需要注意的是加上了回溯与向下递归的判别;
- /**
- * Definition for a binary tree node.
- * struct TreeNode {
- * int val;
- * TreeNode *left;
- * TreeNode *right;
- * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
- * };
- */
- /**
- 迭代法:具象描述递归执行过程
- 1)检查当前p是否为NULL,如果非NULL,当前节点入栈,只要当前节点有左子节点,左子节点入栈;
- 2)1之后,取栈顶元素p,由于1的操作,p没有左子节点,那么访问当前节点的值,且p出栈;
- 3)接下来访问右节点,p=p->right,如果右子节点存在,那么入栈,循环结束;
- **/
- class Solution {
- public:
- vector<int> inorderTraversal(TreeNode* root) {
- if(root==NULL) return {};
- vector<int>res;
- stack<TreeNode*>s;
- TreeNode*p=root;
- s.push(p);
- while(!s.empty()){
- while(p&&p->left){
- p=p->left;s.push(p);
- }
- p=s.top();
- res.push_back(p->val);s.pop();
- //此处先令p=p->right,p可用作第一个while判断是向下递归还是回溯,如果递归过程p为非空,如果为NULl则代表回溯,那么下一轮不用向左递归;
- p=p->right;
- if(p) s.push(p);
- }
- return res;
- }
- };
别人的代码:
- /**
- * Definition for a binary tree node.
- * struct TreeNode {
- * int val;
- * TreeNode *left;
- * TreeNode *right;
- * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
- * };
- */
- class Solution {
- public:
- vector<int> inorderTraversal(TreeNode* root) {
- //使用栈的非递归方法
- vector<int> res;
- stack<TreeNode*> st;
- TreeNode* T=root;
- while(T||!st.empty()){
- //将T的所有左孩子入栈
- while(T){
- st.push(T);
- T=T->left;
- }
- //访问T的元素,然后转到T的右孩子
- if(!st.empty()){
- T=st.top();
- st.pop();
- res.push_back(T->val);
- T=T->right;
- }
- }
- return res;
- }
- };
方法三:Morris Traversal
由于需要用到Thread Binary Tree(线索二叉树),参考 透彻理解线索二叉树 彻底理解线索二叉树
Morris Traversal方法遍历二叉树(非递归,不用栈,O(1)空间)
对于n个节点的二叉树,左右孩子指针为2n个,利用的指针为n-1个,没有利用的指针为n+1个;利用空链域存储前驱和后继:
记ptr指向二叉链表中的一个结点,以下是建立线索的规则:
(1)如果ptr->lchild为空,则存放指向中序遍历序列中该结点的前驱结点。这个结点称为ptr的中序前驱;
(2)如果ptr->rchild为空,则存放指向中序遍历序列中该结点的后继结点。这个结点称为ptr的中序后继;
当然,Morris遍历只用到了线索二叉树的思想和部分操作,线索二叉树的更细节的东西此处不赘述。对于本题,实际上只用到了对叶节点的右指针的线索化,以及通过线索化的指针进行回溯。主要有以下两点:
#1 对所有叶节点的右指针的线索化,令其指向中序遍历的后继节点;
#2 通过线索化的节点,访问中序遍历的后继节点,并恢复被线索化的节点;
参考:二叉树的遍历:先序中序后序遍历的递归与非递归实现及层序遍历
C++代码如下:O(1)空间复杂度,O(n)时间复杂度
- /**
- * Definition for a binary tree node.
- * struct TreeNode {
- * int val;
- * TreeNode *left;
- * TreeNode *right;
- * TreeNode(int x) : val(x), left(NULL), right(NULL) {}
- * };
- */
- class Solution {
- public:
- vector<int> inorderTraversal(TreeNode* root) {
- //Morris Traversal:右线索化+回溯
- vector<int> res;
- if(!root) return res;
- TreeNode *p=root;
- while(p){
- //定义两个节点指针变量p和p的左孩子pLeft
- TreeNode *pLeft=p->left;
- if(pLeft){
- //访问p的左孩子的最右子孩子(即pLeft右孩子的右孩子的右孩子...)
- //线索化之前pLeft的最右子孩子的right指针指向NULL,
- //线索化之后pLeft的最右子孩子的right指向中序遍历中该节点的后继节点p
- //所以循环终止条件为pLeft->right==NULL 或 pLeft->right==p
- while(pLeft->right && pLeft->right!=p){
- pLeft=pLeft->right;
- }
- //此时pLeft代表p的左孩子的最右子孩子
- //pLeft->right==NULL代表没有被线索化,进行线索化然后访问p的左孩子
- if(pLeft->right==NULL){
- pLeft->right=p;
- p=p->left;
- continue;
- }
- //pLeft->right!=NULL代表已经被线索化,此时已经回溯到原来的节点p(第2次访问),所以要恢复被线索化的pLeft的最右子孩子
- else{
- pLeft->right=NULL;
- }
- }
- res.push_back(p->val);
- p=p->right;//访问右孩子(对非叶节点),回溯到中序遍历的后续节点(对叶节点);
- //因为线索化的操作最终是对所有的叶节点进行的,所以上述语句实际有访问右孩子和回溯两个功能;
- }
- return res;
- }
- };
leetcode 94二叉树的中序遍历的更多相关文章
- LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)
94. 二叉树的中序遍历 94. Binary Tree Inorder Traversal 题目描述 给定一个二叉树,返回它的 中序 遍历. LeetCode94. Binary Tree Inor ...
- Java实现 LeetCode 94 二叉树的中序遍历
94. 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? / ...
- Leetcode 94. 二叉树的中序遍历
1.问题描述 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 2.解法一 ...
- LeetCode 94. 二叉树的中序遍历(Binary Tree Inorder Traversal)
题目描述 给定一个二叉树,返回它的中序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 由于 ...
- 【leetcode 94. 二叉树的中序遍历】解题报告
前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> inorderTraversal(TreeNode* root ...
- LeetCode 94 ——二叉树的中序遍历
1. 题目 2. 解答 2.1. 递归法 定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么 递归得到其左子树的数据向量 temp,将 temp 合并到 data 中去 将当前节 ...
- 【LeetCode】94. 二叉树的中序遍历
94. 二叉树的中序遍历 知识点:二叉树:递归:Morris遍历 题目描述 给定一个二叉树的根节点 root ,返回它的 中序 遍历. 示例 输入:root = [1,null,2,3] 输出:[1, ...
- Leetcode题目94.二叉树的中序遍历(中等)
题目描述: 给定一个二叉树,返回它的中序遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 思路解析: 1 ...
- leetcode刷题-94二叉树的中序遍历
题目 给定一个二叉树,返回它的中序 遍历. 实现 # def __init__(self, x): # self.val = x # self.left = None # self.right = N ...
随机推荐
- 配置maven的国内镜像
pom.xml文件出现错误标记,一般是相关的maven资源没有下载完整. 1,配置maven的国内镜像,保证能够顺利下载maven中配置的资源. 在maven的配置文件 settings.xml ...
- selenium入门学习
在写爬虫的学习过程中,经常会有一些动态加载,有些是可以动过接口直接获取到,但是实在没办法,所以学习下selenium. 首先百度一下: Selenium [1] 是一个用于Web应用程序测试的工具. ...
- @Validated @RequestBody @RequestParam配合使用校验参数
1. @Validated @RequestBody 配合使用 两者搭配进行参数的校验,要想自己捕获该异常,需要自定义全局异常处理器 2. @Validated @RequestParam 配合使 ...
- Java程序员常用的Linux命令01——linux命令基础
1.显示日期的命令date 显示日期: [root@localhost ~]# date 显示年月日: [root@localhost ~]# date '+%Y%m%d' 2.显示日历指令cal 显 ...
- 网络初级篇之OSPF(二)实验
一.实验目的: 下面关于OSPF的实验,仔细看配置过程,以增加对OSPF的理解. 二.实现目标: 使用OSPF实现所有主机之间的通信 三.配置过程: 1.AR1的配置过程: ...
- c++ 实现https网页上的图片爬取
一.主要的原理 我们通过发送一个http请求,获得目标网页的html源代码,然后通过正则表达式获取到图片的URL,把该网页的所有的图片都保存到一个文件夹,这就是整个软件的流程. 二.具体的实践 现在很 ...
- Codeforces Round #344 (Div. 2) 631 C. Report (单调栈)
C. Report time limit per test2 seconds memory limit per test256 megabytes inputstandard input output ...
- html base标签 target=_parent使用介绍
<base>标签为页面上的所有链接规定默认地址或默认目标. 通常情况下,浏览器会从当前文档的URL中提取相应的元素来填写相对URL中的空白. 使用<base> 标签可以改变这一 ...
- Django学习系列17:在模板中渲染待办事项
前面提到的问题中在表格中显示多个待办事项 是最后一个容易解决的问题.要编写一个新单元测试,检查模板是否也能显示多个待办事项: lists/tests.py def test_displays_all_ ...
- nginx-轮询、权重、ip_hash 、fair模式
在 linux 下有 Nginx.LVS.Haproxy 等等服务可以提供负载均衡服 务,而且 Nginx 提供了几种分配方式(策略): 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器 ...