1. 题目

2. 解答

2.1. 递归法

定义一个存放树中数据的向量 data,从根节点开始,如果节点不为空,那么

    1. 将当前节点的数值加入到 data 中
    1. 递归得到其左子树的数据向量 temp,将 temp 合并到 data 中去
    1. 递归得到其右子树的数据向量 temp,将 temp 合并到 data 中去
/**
* 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> preorderTraversal(TreeNode* root) { vector<int> data = {};
vector<int> temp = {}; if (root != NULL)
{
data.push_back(root->val);
temp = preorderTraversal(root->left);
data.insert(data.end(),temp.begin(),temp.end());
temp = preorderTraversal(root->right);
data.insert(data.end(),temp.begin(),temp.end());
} return data;
}
};
2.2. 迭代法

定义一个存放树中节点的栈 node_stack 和存放数据的向量 data,从根节点开始,如果节点不为空或者栈非空,循环以下过程:

    1. 如果节点非空,将节点的值加入 data,如果节点有右孩子,将节点右孩子压入栈,节点指向其左孩子,循环直到节点为空
    1. 如果节点为空,栈非空,则弹出栈顶节点
/**
* 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> preorderTraversal(TreeNode* root) { vector<int> data = {};
stack<TreeNode*> node_stack;
TreeNode* temp = root; while (temp || !node_stack.empty())
{
while(temp != NULL)
{
data.push_back(temp->val);
if (temp->right) node_stack.push(temp->right);
temp = temp->left;
} // 若最后一个节点没有右子节点,栈为空
if (!node_stack.empty()) // 栈非空
{
temp = node_stack.top();
node_stack.pop();
}
} return data;
}
};
2.3. Morris 遍历法

前面两种方法要么需要函数栈要么需要人工栈,其空间复杂度为 \(O(n)\),而 Morris 遍历法可以做到在不影响时间复杂度的情况下做到空间复杂度为 \(O(1)\)。

定义一个存放数据的向量 data,从根节点开始,如果当前节点非空,循环以下过程:

    1. 如果当前节点没有左孩子,将当前节点的值加入到 data 中,当前节点指向其右孩子
    1. 如果当前节点有左孩子,则寻找当前节点的前驱节点,即节点值小于该节点值并且值最大的节点,也即当前节点左子树中值最大的节点
    • a) 如果前驱节点没有右孩子,前驱节点右孩子指向当前节点,将当前节点的值加入到 data 中,当前节点指向其左孩子
    • b) 如果前驱节点右孩子为当前节点,当前节点指向其右孩子,前驱节点右孩子设为空(恢复原有树结构)

/**
* 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> preorderTraversal(TreeNode* root) { vector<int> data = {};
TreeNode* cur = root;
TreeNode* pre = NULL; while (cur)
{
if (cur->left == NULL)
{
data.push_back(cur->val);
cur = cur->right;
} else
{ // 寻找前驱结点
pre = cur->left;
while (pre->right != cur && pre->right)
{
pre = pre->right;
} if (pre->right == NULL)
{
data.push_back(cur->val);
pre->right = cur;
cur = cur->left;
}
else
{
cur = cur->right;
pre->right = NULL;
}
}
} return data; }
};

参考资料

获取更多精彩,请关注「seniusen」!

LeetCode 144 ——二叉树的前序遍历的更多相关文章

  1. LeetCode 144. 二叉树的前序遍历(Binary Tree Preorder Traversal)

    144. 二叉树的前序遍历 144. Binary Tree Preorder Traversal 题目描述 给定一个二叉树,返回它的 前序 遍历. LeetCode144. Binary Tree ...

  2. Java实现 LeetCode 144 二叉树的前序遍历

    144. 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] /** * Definition for a ...

  3. Leetcode 144.二叉树的前序遍历

    1.题目描述 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 2.解法 ...

  4. 【leetcode 144. 二叉树的前序遍历】解题报告

    前往二叉树的:前序,中序,后序 遍历算法 方法一:递归 vector<int> res; vector<int> preorderTraversal(TreeNode* roo ...

  5. LeetCode 144. 二叉树的前序遍历(Binary Tree Preorder Traversal)

    题目描述 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 解题思路 由 ...

  6. LeetCode 144. 二叉树的前序遍历 (非递归)

    题目链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal/ 给定一个二叉树,返回它的 前序 遍历. /** * Defi ...

  7. LeetCode:二叉树的前序遍历【144】

    LeetCode:二叉树的前序遍历[144] 题目描述 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 题目分析 如果用递 ...

  8. 【LeetCode】144. 二叉树的前序遍历

    144. 二叉树的前序遍历 知识点:二叉树:递归:Morris遍历 题目描述 给你二叉树的根节点 root ,返回它节点值的 前序 遍历. 示例 输入:root = [1,null,2,3] 输出:[ ...

  9. Leetcode(144)-二叉树的前序遍历

    给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? 二叉树的前序遍历有递归 ...

随机推荐

  1. python 基于udp 连接

    #udp 服务端 #导入socket模块 from socket import * #ip加端口 类型为元组 ip_port=('127.0.0.1',8002) #最大接收字节 buffer_siz ...

  2. sql server 中判断分组排序的使用示例

    现在需要查询一组数据,是对一列字段(column01)的数据分范围查询后分组排序: select (case when [column01] >0 AND [column01]<= 500 ...

  3. Spring 整合Mybatis dao原始方法

    先看一下项目图,基本就理解了整合的内容 这次主角不再是Mybats的配置文件SqlMapConfig.xml了,而是Spring的applicationContext.xml applicationC ...

  4. iOS原生混合RN开发最佳实践

    iOS原生混合RN开发详解 做过原生iOS开发或者Android开发的同学们肯定也都了解Hybrid,有一些Hybrid的开发经验,目前我们企业开发中运用最广泛的Hybrid App技术就是原生与H5 ...

  5. php中的引用

    $var1 = 'zhuchunyu'; $var2 = ""; function foo($vaa){ global $var1,$var2; if (!$vaa){ $var2 ...

  6. .Net core 使用Jenkins + Docker + Azure Devops 傻瓜式部署

    这几天一直在搞 Jenkins + Docker + Azure Devops 部署,因为这种方式部署真的非常的省心,而且速度快,方便快捷,等等无数优点,感谢我的单身领导的支持,当然也感谢 晓晨大神, ...

  7. [读书笔记] Spring MVC 学习指南 -- 第一章

    控制反转(Inversion of Control, IoC)/ 依赖注入: 比如说,类A依赖于类B,A需要调用B的某一个方法,那么在调用之前,类A必须先获得B的一个示例引用. 通常我们可以在A中写代 ...

  8. JS this总结

    JS中一切皆对象,this关键字出现在对象定义时的成员(属性和方法)里,因此this指向的是一个JS对象,这个JS对象具体是哪一个的确定是在运行时确定的. 非严格模式: 1.作为对象成员:对象调用对象 ...

  9. Appointment Helper

    using System; using Microsoft.Xrm.Sdk; using Microsoft.Crm.Sdk.Messages; using Microsoft.Xrm.Sdk.Que ...

  10. [转载zz] Python3 输入和输出之序列化与反序列化

    http://www.runoob.com/python3/python3-inputoutput.html pickle 模块 python的pickle模块实现了基本的数据序列和反序列化. 通过p ...