一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第24天,点击查看活动详情
题目(Binary Tree Preorder Traversal)
链接:https://leetcode-cn.com/problems/binary-tree-preorder-traversal
解决数:2498
通过率:71%
标签:栈 树 深度优先搜索 二叉树
相关公司:bytedance amazon microsoft
给你二叉树的根节点 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
进阶: 递归算法很简单,你可以通过迭代算法完成吗?
思路
前序遍历的定义:对每个节点,都是先处理当前节点,对它执行我们的处理逻辑,再递归它的左子树,再递归它的右子树,对子树中的节点执行相同的逻辑。
代码
const preorderTraversal = (root) => {
const res = [];
const preOrder = (root) => {
if (root == null) return;
res.push(root.val);
preOrder(root.left);
preOrder(root.right);
};
preOrder(root);
return res;
}
func preorderTraversal(root *TreeNode) []int {
res := []int{}
var preOrder func(*TreeNode)
preOrder = func(root *TreeNode) {
if root == nil {
return
}
res = append(res, root.Val)
preOrder(root.Left)
preOrder(root.Right)
}
preOrder(root)
return res
}
迭代版
维护一个栈 stack,模拟递归的压栈出栈。 比照递归DFS,我们首先让左子节点尽可能地压入栈:
while (root) {
res.push(root.val);
if (root.right) stack.push(root.right);
root = root.left;
}
循环结束时,栈顶的节点是位于树底部最左的一个左子节点,让它出栈,带出它的右子节点入栈(如果有)。
并且这个右子节点,也要重复前面的逻辑『让左节点尽可能的压入栈』,可以看到这部分代码重复了两次:
while (stack.length) {
root = stack.pop();
res.push(root.val);
if (root.right) stack.push(root.right);
root = root.left;
while (root) {
res.push(root.val);
if (root.right) stack.push(root.right);
root = root.left;
}
}
没有了左节点可入栈,就取出栈顶的节点,重复上面的操作,栈中节点的出栈,“牵扯”出所有的右子树,从而遍历了整个树。
我们知道,前序遍历是在递归左子树和递归右子树之前,处理当前节点,对迭代版来说,就是压栈之前做事——把节点值推入 res 数组。
代码
const preorderTraversal = (root) => {
const res = [];
const stack = [];
while (root) {
res.push(root.val);
if (root.right) stack.push(root.right);
root = root.left;
}
while (stack.length) {
root = stack.pop();
res.push(root.val);
if (root.right) stack.push(root.right);
root = root.left;
while (root) {
res.push(root.val);
if (root.right) stack.push(root.right);
root = root.left;
}
}
return res;
};