[LeetCode] 问题系列 - Binary Tree Traversal

从大的层面讲,Binary Tree 可以用DFS和BFS。

  • 对于BFS,我们需要 iterative with queue
  • 对于DFS,Binary Tree 有三种traversal的方式:
    ** Inorder Traversal: left -> root -> right
    ** Preoder Traversal: root -> left -> right
    ** Postoder Traveral: left -> right -> root

记忆方式:order的名字指的是root在什么位置。left,right的相对位置是固定的。

图片来源:https://leetcode.com/articles/binary-tree-right-side-view/

对于时间复杂度来说,基本上都是O(n),因为要访问所有的点。
对于空间复杂度来说,BFS取决于扫描过程中每层的node数,就是树的宽度,而DFS取决于扫描过程中树的深度。最坏情况两个都是O(n)。

本文重点讨论iterative和recursive方法。对于morris,另开一篇介绍。

Inorder Traversal

首先是recursion写法,相对简单:

// left->root->right
public List inorderTraversal(TreeNode root) {
    List res = new ArrayList<>();
    if (root == null) {
        return res;
    }
    res.addAll(inorderTraversal(root.left));
    res.add(root.val);
    res.addAll(inorderTraversal(root.left));
}

如果用iteration:

public List inorderTraversal(TreeNode root) {
    List res = new ArrayList<>();
    if (root == null) {
        return res;
    }
    Stack stack = new Stack<>();
    TreeNode cur = root;
    while (cur != null || !stack.isEmpty()) {
        while (cur != null) { // 把左路径上遇到的点都放进stack里面
            stack.push(cur);
            cur = cur.left;
        } // while循环结束的时候,cur==null
        cur = stack.pop();
        res.add(cur.val);
        cur = cur.right;
    }
    return res;
}

Preorder Traversal

首先是recursion写法,相对简单:

// root->left->right
public List preorderTraversal(TreeNode root) {
    List res = new ArrayList<>();
    if (root == null) {
        return res;
    }
    res.add(root.val);
    res.addAll(inorderTraversal(root.left));
    res.addAll(inorderTraversal(root.left));
}

如果用iteration:

public List preorderTraversal(TreeNode root) {
    List res = new ArrayList<>();
    if (root == null) {
        return res;
    }
    Stack stack = new Stack<>();
    stack.push(root);
    TreeNode cur = root;
    while (!stack.isEmpty()) {
        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;
}

Postorder Traversal

首先是recursion写法,相对简单:

// left->right->root
public List preorderTraversal(TreeNode root) {
    List res = new ArrayList<>();
    if (root == null) {
        return res;
    }
    res.addAll(inorderTraversal(root.left));
    res.addAll(inorderTraversal(root.left));
    res.add(root.val);
}

如果用iteration:

public List preorderTraversal(TreeNode root) {
    List res = new LinkedList<>(); // 便于Insert操作
    if (root == null) {
        return res;
    }
    Stack stack = new Stack<>();
    stack.push(root);

    while (!stack.isEmpty()) {
        TreeNode node = stack.pop();
        res.add(0, node.val); // 因为这一步,所以转变成了root->right->left
        if (node.left != null) {
            stack.push(node.left);
        }
        if (node.right != null) {
            stack.push(node.right);
        }
    }
    return res;
}

你可能感兴趣的:([LeetCode] 问题系列 - Binary Tree Traversal)