Binary Tree Traversal (DFS)

This topic serves as an excellent introduction to graph search and divide and conquer. Most (80%) of the BT questions can be solved with D&C. How can you apply the same problem to the left subtree and right subtree?

Preorder Traversal (LC.144)

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

Analysis

Traverse - traverse the entire tree and add nodes in a certain order. preorder will add root.val in the beginning, inorder will add root.val in the middle, and postorder will add root.val in the end.

D&C - the boss breaks down his task into the same subproblems and assign his employees to do it then report to the boss when they are done. *One major difference b/w traverse and D&C is that D&C must have a return value (the report to the boss).

Iteratively - use an explicit stack and be careful with the ordering. Iterative DFS has the opposite ordering as the recursive DFS.

Traverse

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    preorderTraverse(root, result);
    return result;
}

private void preorderTraverse(TreeNode root, List<Integer> result) {
    if (root == null)
        return;
    result.add(root.val);
    preorderTraverse(root.left, result);
    preorderTraverse(root.right, result);
}

D&C

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();

    // base case
    if (root == null) {
        return result;
    }

    // divide
    List<Integer> leftSubtree = preorderTraversal(root.left);
    List<Integer> rightSubtree = preorderTraversal(root.right);

    // conquer
    result.add(root.val);
    result.addAll(leftSubtree);
    result.addAll(rightSubtree);

    return result;
}

Iteratively

This is like a regular DFS (w/ opposite ordering). Pretty easy to understand.

public List<Integer> preorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    if (root == null)
        return result;
    Stack<TreeNode> stack = new Stack<>();
    stack.push(root);

    while (!stack.isEmpty()) {
        TreeNode visit = stack.pop();
        result.add(visit.val);
        if (visit.right != null) {
            stack.push(visit.right);
        }
        if (visit.left != null) {
            stack.push(visit.left);
        }
    }

    return result;
}

Inorder Traversal (LC.94)

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

Traverse

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    inorderTraverse(root, result);
    return result;
}

private void inorderTraverse(TreeNode root, List<Integer> result) {
    if (root == null)
        return;
    inorderTraverse(root.left, result);
    result.add(root.val);
    inorderTraverse(root.right, result);
}

D&C

Trace this one. It makes sense to go down all the way to the left, print and backtrack, print then go right, then backtrack.

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();

    // base case
    if (root == null) {
        return result;
    }

    // divide
    List<Integer> leftSubtree = inorderTraversal(root.left);
    List<Integer> rightSubtree = inorderTraversal(root.right);

    // conquer
    result.addAll(leftSubtree);
    result.add(root.val);
    result.addAll(rightSubtree);

    return result;
}

Iteratively

public List<Integer> inorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    if (root == null)
        return result;

    Stack<TreeNode> stack = new Stack<>();
    TreeNode visit = root;

    while(visit != null || !stack.isEmpty()) {
        if (visit != null) {
            stack.push(visit);
            visit = visit.left;
        } else {
            visit = stack.pop();
            result.add(visit.val);
            visit = visit.right;
        }
    }

    return result;
}

Postorder Traversal (LC.145)

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

Traverse

public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    postorderTraverse(root, result);
    return result;
}

private void postorderTraverse(TreeNode root, List<Integer> result) {
    // base case
    if (root == null)
        return;
    postorderTraverse(root.left, result);
    postorderTraverse(root.right, result);
    result.add(root.val);
}

D&C

public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();

    // base case
    if (root == null) {
        return result;
    }

    // divide
    List<Integer> leftSubtree = postorderTraversal(root.left);
    List<Integer> rightSubtree = postorderTraversal(root.right);

    // conquer
    result.addAll(leftSubtree);
    result.addAll(rightSubtree);
    result.add(root.val);

    return result;
}

Iteratively

the key is to understand the use of lastVisit and peek

  • peek is for going right first before root
  • what about lastVisit? make sure you don't step down on the right path again
public List<Integer> postorderTraversal(TreeNode root) {
    List<Integer> result = new ArrayList<>();
    if (root == null)
        return result;

    Stack<TreeNode> stack = new Stack<>();
    TreeNode visit = root, lastVisit = null, peek = null;

    while (visit != null || !stack.isEmpty()) {
        if (visit != null) {
            stack.push(visit);
            visit = visit.left;
        } else {
            peek = stack.peek();

            if (peek.right != null && lastVisit != peek.right) {
                visit = peek.right;
            } else {
                result.add(peek.val);
                lastVisit = stack.pop();
            }
        }
    }

    return result;
}

Time & Space Complexity

duh we need to visit all the nodes so time will be O(V). The stack space is proportional to the height of the tree. Note: the height of tree is not necessarily logn, the worst case can be n, a linear tree. So we have O(h) where a balanced tree can be O(logn) and a linear tree can be O(n).

References

Wikipedia Tree Traversal

ʕ; •`ᴥ•´ʔ

results matching ""

    No results matching ""