题目链接
解题思路
-
递归法
-
前序遍历的顺序是
根节点--> 左子树-->右子树
,简称DLR
-
注意在访问左子树或者右子树的时候,按照同样的方式遍历,直到遍历完整棵树
-
大佬的解题思路:Morris遍历
-
Morris遍历的核心思想是利用树的大量空闲指针,实现空间开销的极限缩减,其前序遍历规则总结如下:
- 新建临时节点,令该节点为
root
- 如果当前节点的左子节点为空格,将当前节点加入答案,并遍历当前节点的右子节点
- 如果当前节点的左子节点不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点:
- 如果前驱节点的右子节点为空,将前驱节点的右子节点设置为当前节点。然后将当前节点加入答案,并将前驱节点的右子节点更新为当前节点
- 如果前驱节点的右子节点为当前节点,将他的右子节点重新设为空。当前节点更新为当前节点的右子节点
- 重复步骤2和步骤3,直到遍历结束
- 新建临时节点,令该节点为
AC代码
//常规的递归法,时间复杂度O(n),空间复杂度O(n)
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> ans = new ArrayList<Integer>();
preorder(root, ans);
return ans;
}
public void preorder(TreeNode root, List<Integer> ans) {
if (root == null) {
return;
}
ans.add(root.val);
preorder(root.left, ans);
preorder(root.right, ans);
}
}
//Morris解法,时间复杂度O(n),空间复杂度O(1)
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if (root == null) {
return res;
}
TreeNode p1 = root, 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;
}
}