Given a binary tree, return the preorder traversal of its nodes' values.
For example:
Given binary tree {1,#,2,3}
,
1 \ 2 / 3
return [1,2,3]
.
分类:二叉树
题意:前序遍历二叉树
解法1:递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root!=null) helper(res,root);
return res;
}
public void helper(List<Integer> res,TreeNode n){
res.add(n.val);
if(n.left!=null) helper(res, n.left);
if(n.right!=null) helper(res, n.right);
}
}
解法2:使用栈模拟递归
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root==null) return res;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.add(root);
while(!stack.isEmpty()){
TreeNode cur = stack.pop();
res.add(cur.val);
if(cur.right!=null) stack.add(cur.right);//右节点先进栈,从而后出栈
if(cur.left!=null) stack.add(cur.left);//左节点先进栈,从而先出栈
}
return res;
}
}
解法3:morris二叉树遍历,空间O(1),时间O(n)
遍历过程如下:对于某个节点root,判断其是否有左子树,没有,则访问该节点,将当前节点设置为其右节点,重复上述过程。
有左子树,遍历获得左子树最右边的节点(也就是前序遍历中,左子树最后一个访问的节点),
如果这个节点的right为空,将这个节点的right设置为当前节点root,访问root,将当前节点设置为root的左节点
如果该节点right已经有指向,说明这个节点已经被线索化了,将当前节点设置为root的右节点,设置right为null清除线索
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class Solution {
public List<Integer> preorderTraversal(TreeNode root) {
List<Integer> res = new ArrayList<Integer>();
if(root==null) return res;
TreeNode cur = root;
TreeNode pre = null;
while(cur!=null){//当前节点不为空,也就是没有到最后
if(cur.left==null){//如果当前节点左子树为空
res.add(cur.val);//访问当前节点
cur = cur.right;//设置其右节点为当前节点
}else{//如果左子树不为空
pre = cur.left;
while(pre.right!=null&&pre.right!=cur){//获得左子树最右边的节点
pre = pre.right;
}
if(pre.right==null){//如果最右边节点没有被线索化
pre.right = cur;//线索化
res.add(cur.val);//访问当前节点
cur = cur.left;//设置其左节点为当前节点
}else{//如果被线索化了,说明这次访问,是为了访问其线索节点
pre.right = null;//取消线索化
cur = cur.right;//线索节点
}
}
}
return res;
}
}