144. 二叉树的前序遍历
Given a binary tree, return the preorder traversal of its nodes' values.
Example:
Input:
[1,null,2,3]
1 \ 2 / 3 Output:[1,2,3]
Follow up: Recursive solution is trivial, could you do it iteratively?
二叉树的先序遍历。
这个比较简单,直接看递归和非递归的代码实现
class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list=new ArrayList<>(); process(root,list); return list; } public void process(TreeNode node,List<Integer> list){ if(node==null){ return; } list.add(node.val); process(node.left,list); process(node.right,list); } }
先序遍历:中左右
非递归的方式用stack来实现(深度优先遍历用stack,广度优先用队列)
对当前节点压入stack,弹出并打印(中),再对cur压入右左(左右)
class Solution { public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list=new ArrayList<>(); if(root==null){ return list; } Stack<TreeNode> stack=new Stack<>(); stack.push(root); while(!stack.isEmpty()){ TreeNode cur=stack.pop(); list.add(cur.val); if(cur.right!=null){ stack.push(cur.right); } if(cur.left!=null){ stack.push(cur.left); } } return list; } }
先序遍历还可以用Morris序来遍历
时间复杂度为O(1)
Morris遍历细节:
假设cur来到当前节点,cur从头节点开始
1、cur没有左孩子,cur向右移动
2、cur有左孩子,找到左孩子的最右孩子
a:如果右孩子的右指针为空,则让右指针指向当前节点,当前节点向左移动,回到1;(表示第一次到这个节点)
b:如果右孩子的右指针指向当前节点,让右指针指向null,当前节点向右移动;(表示第二次到这个节点)
3、当cur为空遍历结束
这个过程说明了:如果cur有左孩子遍历时会两次经过该节点, 否则只会一次经过该节点
下面是Morris序遍历的代码:
public void morrisTraversal(TreeNode head){ if(head==null) { return; } TreeNode cur=head; TreeNode mostRight; while(cur!=null){ mostRight=cur.left; if(mostRight!=null){ //有左节点 while (mostRight.right!=null&&mostRight.right!=cur){ mostRight=mostRight.right; } if(mostRight.right==null){ mostRight.right=cur; cur=cur.left; continue; }else{ mostRight.right=null; } } cur=cur.right; } }
Morris序改先序遍历
public List<Integer> preorderTraversal(TreeNode root) { List<Integer> list=new ArrayList<>(); if(root==null){ return list; } TreeNode cur=root; TreeNode mostRight; while(cur!=null){ mostRight=cur.left; if(mostRight!=null){ //有左节点 while (mostRight.right!=null&&mostRight.right!=cur){ mostRight=mostRight.right; } if(mostRight.right==null){ //第一次来到cur list.add(cur.val);//注意这行的位置,不能放到下面,因为cur会移动 mostRight.right=cur; cur=cur.left; continue; }else{ //第二次来到cur mostRight.right=null; } }else{ //只会来到一次的cur list.add(cur.val); } cur=cur.right; } return list; }