力扣 - 144. 二叉树的前序遍历
题目
思路1(递归)
- 前序先遍历根节点,然后左孩子,然后右孩子
- 使用递归解题
代码
class Solution {
List<Integer> res = new LinkedList<>();
public List<Integer> preorderTraversal(TreeNode root) {
preOrder(root);
return res;
}
public void preOrder(TreeNode root) {
if (root == null) {
return;
}
res.add(root.val);
preOrder(root.left);
preOrder(root.right);
}
}
复杂度分析
- 时间复杂度:\(O(N)\),其中 N 为二叉树的结点数
- 空间复杂度:\(O(N)\)
思路2(迭代)
- 用栈来遍历
- 和层序遍历有些类似,不过不用队列,而是用栈
代码
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
if (root == null) {
return res;
}
Deque<TreeNode> stack = new LinkedList<>();
while (!stack.isEmpty() || root != null) {
while (root != null) {
res.add(root.val);
// 入栈
stack.push(root);
root = root.left;
}
root = stack.pop().right;
}
return res;
}
}
复杂度分析
- 时间复杂度:\(O(N)\),其中 N 为二叉树的结点数
- 空间复杂度:\(O(N)\)
思路3(Morris遍历)
- 如果左孩子不为空
- 找到左子树的最右端的节点
- 如果该节点的right是null,那么将其right指向当前节点,并且将当前节点加入res
- 否则将其right置为null
- 找到左子树的最右端的节点
- 如果左孩子为空
- 直接将当前节点加入res
- 每次循环结束都将指针指向当前节点的右孩子right
代码
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new LinkedList<>();
TreeNode p1 = root;
TreeNode p2 = null;
while (p1 != null) {
p2 = p1.left;
if (p2 != null) {
while (p2.right != null && p2.right != p1) {
p2 = p2.right;
}
if (p2.right == null) {
res.add(p1.val);
// 如果左子树的最右节点是指向空的,那么就先把他指向子树的父节点
p2.right = p1;
// 同时指针
p1 = p1.left;
continue;
} else {
p2.right = null;
}
} else {
res.add(p1.val);
}
p1 = p1.right;
}
return res;
}
}
复杂度分析
- 时间复杂度:\(O(N)\),其中 N 为二叉树的结点数
- 空间复杂度:\(O(1)\)
我走得很慢,但我从不后退!

浙公网安备 33010602011771号