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 ...
随机推荐
- 检查linux是否安装java、tomcat、mysql
linux下,查看安装软件 1.linux下的java Java -version 如果出现java版本,证明java安装成功. 2.linux下的tomcat 2.1.检查linux是否安装tomc ...
- Proxy.newInstance与InvocationHandler的使用示例
先定义一个接口,根据代理模式的原理,被代理类与代理类都要实现它. public interface Person { void eat(); } 再写一个实际执行任务的类(被代理类): public ...
- 17、RAID和LVM
一.RAID 1.什么是raid 磁盘阵列(Redundant Arrays of Independent Drives,RAID),有"独立磁盘构成的具有冗余能力的阵列"之意. ...
- openstack dashboard开启https
前提条件: 1.基于http的dashboard能正常访问 2.拥有ssl证书 第一步:修改/etc/openstack-dashboard/local_settings 在DEBUG = False ...
- 记一次启动Tomcat 控制台以及log4j 乱码问题
Tomcat启动乱码 问题描述:当你发现你的Tomcat启动时乱码了,而你只是换了个Tomcat版本而已. 在找到真正的问题之前,我在网上百度了N多的资料,都试过了,但是都不行.1.修改了 windo ...
- 单节点oracle、ASM 详细安装步骤
目录 1.安装环境 2.系统要求 2.1 Linux安装Oracle系统要求 1.查看RAM和交换空间以及磁盘大小 2.检查所需软件包 3.配置host和主机名 2.2修改操作系统核心参数 1.创建相 ...
- tornada-数据库
数据库 torndb安装 连接初始化 执行语句 execute execute_rowcount 查询语句 get query 与Django框架相比,Tornado没有自带ORM,对于数据库需要自己 ...
- Apk反编译那些事
参考博客: https://blog.csdn.net/cbd_2012/article/details/91410119 https://mp.weixin.qq.com/s?__biz=MzI0N ...
- 浅析Java web程序之客户端和服务器端交互原理
原文链接: https://www.iteye.com/topic/470019 1. 协议 a. TCP/IP整体构架概述 TCP/IP协议并不完全符合OSI的七层参考模型.传统的开放式系统互连参考 ...
- ionic实现下载文件并打开功能(file-transfer和file-opener2插件)
作为一款app,下载文件功能,和打开文件功能,在某些场景下还是十分有必要的.使用cordova-plugin-file-transfer和cordova-plugin-file-opener2这两个插 ...