给你二叉树的根节点 root ,返回它节点值的 前序 遍历。
示例 1:
输入:root = [1,null,2,3]
输出:[1,2,3]
示例 2:
输入:root = []
输出:[]示例 3:
输入:root = [1]
输出:[1]
示例 4:
输入:root = [1,2]
输出:[1,2]
示例 5:
输入:root = [1,null,2]
输出:[1,2]提示:
树中节点数目在范围 [0, 100] 内
-100 <= Node.val <= 100
进阶:递归算法很简单,你可以通过迭代算法完成吗?
思路:
- 迭代:
- 利用栈(数组)实现,从根节点开始不断向下遍历左子节点,并且将每个节点入栈,直至左子节点不存在(为空)。
- 接下来,获取栈顶的节点top,获取top的右子节点,从栈中弹出栈顶节点top
- 以top节点为基准,找top的左子节点,重新开始新一轮遍历
根节点 -> 左子节点(不断向下直至左子节点为空) -> 弹出栈顶节点top -> 获取top右子节点 -> 栈顶元素出栈 -> 以top从头开始新一轮左子节点遍历 -> ...
- 递归
时间复杂度:
O(n),其中 n 是二叉树的节点数,每个节点都遍历到。
空间复杂度:
O(n),为迭代过程中显式栈的开销,平均情况下为 O(log n),最坏情况下树呈现链状,为 O(n)。
Go版本:
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
// 方法1 迭代
func preorderTraversal(root *TreeNode) []int {
array := make([]int, 0)
stack := make([]*TreeNode, 0)
for root != nil || len(stack) > 0 {
// 不断遍历左子树
for root != nil {
array = append(array, root.Val) // result, finally return
stack = append(stack, root) // push
root = root.Left
}
// 左子树遍历完了,开始从下往上遍历右子树(每次找栈顶指针,然后pop出栈)
if len(stack) > 0 {
root = stack[len(stack) - 1] // 获取栈顶元素
root = root.Right
stack = stack[: len(stack) - 1] // pop
}
}
return array
}
// 方法2 递归
var array []int
func preorderTraversal(root *TreeNode) []int {
array = make([]int, 0)
dfs(root)
return array
}
func dfs(root *TreeNode) {
if root == nil {
return
}
array = append(array, root.Val)
dfs(root.Left)
dfs(root.Right)
}
C++版本:
vector<int> preorderTraversal(TreeNode* root) {
vector<int> v;
stack<TreeNode*> s;
while (root != NULL || !s.empty()) // 注意是||不是&&
{
while (root != NULL)
{
v.push_back(root->val); // cout
s.push(root);
root = root->left;
}
// 若跳出上面循环,表示当前节点的left节点为NULL
if (!s.empty())
{
// 接下来寻找当前节点的right节点,并且当前root节点已无作用->pop
root = s.top();
s.pop();
root = root->right;
}
}
return v;
}