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. NodeJ node.js Koa2 跨域请求

    Koa2 .3 跨域请求 Haisen's  需求分析 (localhost:8080 = 前端  [请求]  localhost:8081 = 服务器 ) 1.一个前台    一个服务器    前台 ...

  2. 12种开源Web安全扫描程序

    转自:https://blog.csdn.net/wh211212/article/details/78620963 赛门铁克的一个有趣的报告显示,76%的被扫描网站有恶意软件 如果您使用的是Word ...

  3. window下pip install Scrapy报错解决方案

    1.首先打开https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted,找到对应版本的Twisted并下载到你的文件夹. 2.利用pip install命令 ...

  4. 新人成长之入门Vue.js常用指令介绍(一)

    写在前面 作为一个刚步入职场工作的新人,对于公司中所用的技术和框架基本上不懂,只能从最基础的开始做起,进入公司接触的第一个框架就是前端框架Vue.js,几个功能做下来,觉得Vue.js首先学习起来真的 ...

  5. Java性能优化的50个细节

    在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. 1. 尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时 ...

  6. Java Web项目里 classpath 具体指哪个路径

    classpath路径指什么 只知道把配置文件如:mybatis.xml.spring-web.xml.applicationContext.xml等放到src目录(就是存放代码.java文件的目录) ...

  7. 微信小程序 唯一标识 加减

    var nums = 'goods_list[' + e.currentTarget.dataset.indexs+'].goods_num' //console.log(nuns) var num ...

  8. python代理爬取存入csv文件

    爬取高匿代理 from urllib import request import re import time f = open('西1.csv','w',encoding='GBK') header ...

  9. 虚拟机的三种联网模式(桥接模式、NAT 模式、仅主机模式)

    虚拟机的网络连接方式分为三种,分别是桥接模式.NAT 模式.和仅主机模式,三种连接模式存在着一定的差异,那么我们该如何选择适合自己的连接模式呢? 1.桥接模式:在此模式下,虚拟机相当于一台独立的电脑, ...

  10. macos 安装 brew

    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ...