Appearance
0144-二叉树的前序遍历
https://leetcode.cn/problems/binary-tree-preorder-traversal
给你二叉树的根节点 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
进阶:递归算法很简单,你可以通过迭代算法完成吗?
思路 : 递归
前序遍历 : 根左右,递归调用
参考代码
csharp
public class Solution {
List<int> list = new List<int>();
private void dfs(TreeNode root){
if(root == null){
return;
}
list.Add(root.val);
dfs(root.left);
dfs(root.right);
}
public IList<int> PreorderTraversal(TreeNode root) {
dfs(root);
return list;
}
}
思路2:迭代【官方】
递归调用的时候,隐式的维护了一个栈。
使用迭代的时候,我们需要将这个栈显示的申明出来。
迭代法模板
csharp
public class Solution {
public IList<int> PreorderTraversal(TreeNode root) {
List<int> list = new List<int>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode node = root;
while(stack.Count > 0 || node != null){
//遍历左节点
while(node != null){
// 前序:这里处理
// list.Add(node.val)
stack.Push(node);
node = node.left;
}
//遍历根节点
node = stack.Pop();
//中序这里处理
//list.Add(node.val);
//遍历右节点
node = node.right;
//后续这里处理
// if(node.right == null){
// list.Add(node.val);
// }
}
return list;
}
}
参考代码
csharp
public class Solution {
public IList<int> PreorderTraversal(TreeNode root) {
List<int> list = new List<int>();
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode node = root;
while(stack.Count > 0 || node != null){
while(node != null){
list.Add(node.val);
stack.Push(node);
node = node.left;
}
node = stack.Pop();
node = node.right;
}
return list;
}
}
思路3:Morris算法【官方】
Morris 遍历的核心思想是利用树的大量空闲指针,前序遍历规则如下
- 新建临时节点,令该节点为 root
- 如果当前节点的左子节点为空,将当前节点加入答案,并遍历当前节点的右子节点
- 如果当前节点的左子节点不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱结点
- 如果前屈节点的右子节点为空,将前驱节点的右子节点设置为当前节点。 然后将当前节点加入答案,并将前驱节点的右子节点更新为当前节点。 当前节点更新为当前节点的左子节点 3.1 --> 如果前驱节点的右子节点为空,将前驱节点的右子节点设置为当前节点。然后将当前节点加入答案,并将当前节点更新为当前节点的左子节点。
- 如果前屈节点的右子节点为当前节点,将它的右子节点重新设为空。当前节点更新为当前节点的右子节点。
- 重复步骤2和步骤3,只到遍历结束
AlgoPress