Binary Tree Inorder Traversal

Given a binary tree, return the inorder traversal of its nodes' values.

For example:
Given binary tree {1,#,2,3},

   1
    \
     2
    /
   3

return [1,3,2].

Note: Recursive solution is trivial, could you do it iteratively?

思路:iterative 那么就是模拟dfs过程,也就是stack来模拟整个过程。left, current, right.

从小到大遍历,把左边node全部入栈,然后pop当前点,遇见right node,继续上面这个过程,这样就是每次都是pop接下来第二小的node;

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if(root == null) {
            return list;
        }
        Stack<TreeNode> stack = new Stack<>();
        pushLeft(root, stack);
        
        while(!stack.isEmpty()) {
            TreeNode node = stack.pop();
            list.add(node.val);
            if(node.right != null) {
                pushLeft(node.right, stack);
            }
        }
        return list;
    }
    
    public void pushLeft(TreeNode node, Stack<TreeNode> stack) {
        while(node != null) {
            stack.push(node);
            node = node.left;
        }
    }
}

以上是面试基本要求。如果面试官要求use const space遍历,那么就是接下来要求的,morris travel.
我找了半天,这两个是我见到的比较好的版本,看了大概1个小时,学会了。
http://www.cnblogs.com/AnnieKim/archive/2013/06/15/morristraversal.html

1. 如果当前节点的左孩子为空,则输出当前节点并将其右孩子作为当前节点。

2. 如果当前节点的左孩子不为空,在当前节点的左子树中找到当前节点在中序遍历下的前驱节点。

   a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点。当前节点更新为当前节点的左孩子。

   b) 如果前驱节点的右孩子为当前节点,将它的右孩子重新设为空(恢复树的形状)。输出当前节点。当前节点更新为当前节点的右孩子。

3. 重复以上1、2直到当前节点为空。

http://blog.youkuaiyun.com/linhuanmars/article/details/20187257
算法具体分情况如下:
1. 如果当前结点的左孩子为空,则输出当前结点并将其当前节点赋值为右孩子。
2. 如果当前节点的左孩子不为空,则寻找当前节点在中序遍历下的前驱节点(也就是当前结点左子树的最右孩子)。接下来分两种情况:
 a) 如果前驱节点的右孩子为空,将它的右孩子设置为当前节点(做线索使得稍后可以重新返回父结点)。然后将当前节点更新为当前节点的左孩子。
 b) 如果前驱节点的右孩子为当前节点,表明左子树已经访问完,可以访问当前节点。将它的右孩子重新设为空(恢复树的结构)。输出当前节点。当前节点更新为当前节点的右孩子。

/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
         List<Integer> res = new ArrayList<Integer>();
         TreeNode cur = root;
         TreeNode pre = null;
         
         // Morris Travel. Time: O(n); Space: O(1);
         while(cur!=null){
             if(cur.left == null){
                 res.add(cur.val);
                 cur = cur.right;
             }else{
                 pre = cur.left;
                 //find rightmost node in left tree;
                 while(pre.right!=null && pre.right!=cur){
                     pre = pre.right;
                 }
                 
                 if(pre.right == null){
                     pre.right = cur;
                     cur = cur.left;
                 }else{
                     pre.right = null;
                     res.add(cur.val);
                     cur = cur.right;
                 }
             }
         }
         return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值