67. Binary Tree Inorder Traversal-二叉树的中序遍历(递归与非递归法)

Description

给出一棵二叉树,返回其中序遍历

样例

给出二叉树 {1,#,2,3},

   1
    \
     2
    /
   3

返回 [1,3,2].

挑战 

你能使用非递归算法来实现么?

Solution

算法思路:

  1. 遍历法(递归)
  2. 分治法(递归)
  3. 非递归法实现中序遍历的通用版本(非递归)

    利用 stack 进行 Binary Tree Iterator。

  • stack 中保存一路走到当前节点的路径中所有的节点。
  • stack.peek() 一直指向 iterator 指向的当前节点,存入result中。
  • hasNext() 只需要判断 stack 是否为空。
  • 遍历时如果栈不为空,则返回 stack.peek() 的值,存入result中,并将 iterator 挪到下一个点,对 stack 进行相应的变化。

    挪到下一个点的算法如下:

  1. 如果当前点存在右子树,那么就是右子树中“一路向西”最左边的那个点。
  2. 如果当前点不存在右子树,则是走到当前点的路径中,第一个左拐的点。

1. 遍历法(递归)

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param root: A Tree
     * @return: Inorder in ArrayList which contains node values.
     */
    public List inorderTraversal(TreeNode root) {
        // write your code here
        //Version 1: Traverse 遍历
        List result = new ArrayList<>();
        traverse(root, result);
        return result;
    }
    //1. 递归的定义
    //把以root为根的所有inorder加入result里面
    private void traverse(TreeNode root, List result) {
        //3. 递归的出口
        if (root == null) {
            return;
        }
        //2. 递归的拆解
        traverse(root.left, result);     //左
        result.add(root.val);       //根
        traverse(root.right, result);     //右
    }
}

2. 分治法(递归)

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param root: A Tree
     * @return: Inorder in ArrayList which contains node values.
     */
    public List inorderTraversal(TreeNode root) {
        // write your code here
        //Version 2: Divide & conquer 分治算法
        List result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        //Divide
        List left = inorderTraversal(root.left);
        List right = inorderTraversal(root.right);
        //conquer
        result.addAll(left);
        result.add(root.val);
        result.addAll(right);
        return result;
    }
}

3. 非递归法实现中序遍历的通用版本(非递归)

/**
 * Definition of TreeNode:
 * public class TreeNode {
 *     public int val;
 *     public TreeNode left, right;
 *     public TreeNode(int val) {
 *         this.val = val;
 *         this.left = this.right = null;
 *     }
 * }
 */


public class Solution {
    /*
     * @param root: A Tree
     * @return: Inorder in ArrayList which contains node values.
     */
    public List inorderTraversal(TreeNode root) {
        // write your code here
        // Version 3 :通用的非递归实现中序遍历
        Stack stack = new Stack<>();
        List result = new ArrayList<>();
        
        //一直往左边走,找到最左边的节点,并将路径上的点都入栈
        while (root != null) {
            stack.push(root);
            root = root.left;
        }
        
        while (!stack.isEmpty()) {
            TreeNode node = stack.peek();
            result.add(node.val);
            
            //调整栈的结构,找到下一个点
            //2. 如果当前点不存在右子树,则是走到当前点的路径中,第一个左拐的点
            //就是原路返回(stack.pop()),找到第一个左拐的点
            //相当于左子树遍历完了,该遍历中间和右边了
            if (node.right == null) {
                node = stack.pop();
                while (!stack.isEmpty() && stack.peek().right == node) {
                    node = stack.pop();
                }
            } else {
                //1. 如果当前点存在右子树,那么就是右子树中“一路向左”最左边的那个点
                //就是先向右走一步,然后一直向左走到头的那个点
                node = node.right;
                while (node != null) {
                    stack.push(node);
                    node = node.left;
                }
            }
        }
        return result;
    }
}

你可能感兴趣的:(LintCode)