点击打开题目链接
递归的解法非常简单,代码也比较精简。时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
用栈(Stack
)来保存结点,类似递归。时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
这个算法每个结点需要遍历2次,所以时间复杂度要比之前两种高一些,但是空间复杂度仅为 O ( 1 ) O(1) O(1)。
盗了一张示意图,出处见水印。图片的含义为:每个结点的左子树的最右结点的右指针指向自己(这是为了方便回溯)。
算法核心为:每个结点要经过两遍,第一次经过要找出当前结点左子树的最右结点的位置,然后把它的右指针指向自己;第二次经过时会发现它左子树的最右结点已经指向了自己,说明左子树已经全部遍历完,通过最右结点的右指针走了回来,这时要断开最右指针指向自己的"通道",然后搜索自己的右子树。
/*
* @lc app=leetcode.cn id=144 lang=cpp
*
* [144] 二叉树的前序遍历
*/
// @lc code=start
/**
* 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> res;
TreeNode *temp;
TreeNode *cur = root;
while(cur != NULL)
{
// 左子树为空,搜索右子树
if (cur->left == NULL)
{
res.push_back(cur->val);
cur = cur->right;
}
else
{
// 在左子树上找最右结点
temp = cur->left;
while(temp->right != NULL && temp->right != cur)
temp = temp->right;
// 第一次搜索到这个结点
if (temp->right == NULL)
{
// 先序遍历,把这个结点保存
res.push_back(cur->val);
// 记录一下回溯的位置
temp->right = cur;
// 从左边继续搜索
cur = cur->left;
}
// 第二次遍历
else // temp->right == cur
{
// 还原指针
temp->right = NULL;
// 左边在第一次遍历已经搜索过,向右边搜索
cur = cur->right;
}
}
}
return res;
}
};