10.27
LeetCode 每日一题 144.二叉树的前序遍历
本题其实很简单,就是考察二叉树的前序遍历。
什么是前序遍历:
前序遍历(VLR), 是二叉树遍历的一种,也叫做先根遍历、先序遍历、前序周游,可记做根左右。前序遍历首先访问根结点然后遍历左子树,最后遍历右子树。
方法一:递归
class Solution {
List<Integer> res = new ArrayList<Integer>();
public List<Integer> preorderTraversal(TreeNode root) {
VLR(root);
return res;
}
void VLR(TreeNode root){
if(root == null)
return;
res.add(root.val);
VLR(root.left);
VLR(root.right);
}
}
方法二:栈迭代
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null)
return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root); // 根节点入栈
while(!stack.isEmpty()){ // 当栈为空的时候,则已经遍历完全部节点
TreeNode cur = stack.pop(); //先遍历根节点
res.add(cur.val); // 加入返回的结果集中
// 因为栈是先进后出的,前序遍历是 根->左->右 遍历
// 所以应该将右结点先入栈,左结点后入栈
if(cur.right != null) //当前结点的右结点不为空时,则入栈
stack.push(cur.right);
if(cur.left != null) //当前结点的左结点不为空时,则入栈
stack.push(cur.left);
}
return res;
}
方法三:Morris算法
前两种算法的空间复杂度都是O(n),而这种算法将空间复杂度降低到了O(1)。
morris遍历的实现原则
记作当前节点为cur
-
如果cur无左孩子,cur向右移动(cur=cur.right)
-
如果cur有左孩子,找到cur左子树上最右的节点,记为mostright
-
- 如果mostright的right指针指向空,让其指向cur,cur向左移动(cur=cur.left)
- 如果mostright的right指针指向cur,让其指向空,cur向右移动(cur=cur.right)
实现以上的原则,即实现了morris遍历。
知乎传送门 https://zhuanlan.zhihu.com/p/101321696
class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root == null)
return res;
TreeNode cur = root;
while(cur != null){
if(cur.left == null){
res.add(cur.val);
cur = cur.right;
}else{
TreeNode temp = cur.left;
while(temp.right != null && temp.right != cur){
temp = temp.right;
}
if(temp.right == null){
res.add(cur.val);
temp.right = cur;
cur = cur.left;
}else{
temp.right = null;
cur = cur.right;
}
}
}
return res;
}
}