Skip to content

Recursion

Published: at 10:14 AM

Recursion

Table of Contents

Open Table of Contents

Implementation

Recursion Tree

Each node in the recursion represents a recursion call. The times that a recursive function calls itself is the number of branches of this node.

time and space complexity

TC: O(branch ^ level) // the total TC of all nodes in the recursion tree For binary recursion tree, the number of nodes on the bottom level dominates the total TC, i.e. O(n)

SC: O(height) // the total SC of all nodes on the longest single path

Some problems can have top-half and bottom-half recursion trees (e.g. merge sort) top-half accounts for partitioning, bottom-half accounts for merging TC: O(n) + O(nlogn) = O(nlogn) SC: O(logn) + O(n) = O(n)

Use Case and Practice

DFS backtracking

Find all possible

n queens

Get all valid ways of putting N Queens on an N * N chessboard so that no two Queens threaten each other.

Assumptions

N > 0

Return

A list of ways of putting the N Queens
Each way is represented by a list of the Queen's y index for x indices of 0 to (N - 1)
public class Solution {
  public List<List<Integer>> nqueens(int n) {
    // Write your solution here
    List<List<Integer>> ans = new ArrayList<>();
    dfs(n, 0, new ArrayList<Integer>(), ans);
    return ans;
  }

  private void dfs(int n, int index, List<Integer> board, List<List<Integer>> ans) {
    if (index == n) {
      ans.add(new ArrayList<>(board));
      return;
    }
    for (int i = 0; i < n; i++) {
      if (isValid(board, index, i)) {
        board.add(i);
        dfs(n, index + 1, board, ans);
        board.remove(index);
      }
    }
  }

  private boolean isValid(List<Integer> board, int index, int i) {
    for (int j = 0; j < index; j++) {
      if (i == board.get(j)) {
        return false;
      }
      if (Math.abs(index - j) == Math.abs(i - board.get(j))) {
        return false;
      }
    }
    return true;
  }
}

reverse linked list

Reverse pairs of elements in a singly-linked list.

public class Solution {
  public ListNode reverseInPairs(ListNode head) {
    // Write your solution here
    if (head == null || head.next == null) {
      return head;
    }
    ListNode third = head.next.next;
    ListNode second = head.next;
    second.next = head;
    head.next = reverseInPairs(third);
    return second;
  }
}

lowest common ancestor I (LCA)

Given two nodes in a binary tree, find their lowest common ancestor.

Assumptions

There is no parent pointer for the nodes in the binary tree

The given two nodes are guaranteed to be in the binary tree
public class Solution {
  public TreeNode lowestCommonAncestor(TreeNode root, TreeNode one, TreeNode two) {
    // Write your solution here.
    if (root == null) {
      return null;
    }
    if (root == one || root == two) {
      return root;
    }
    TreeNode left = lowestCommonAncestor(root.left, one, two);
    TreeNode right = lowestCommonAncestor(root.right, one, two);
    if (left != null && right == null) {
      return left;
    } else if (left == null && right != null) {
      return right;
    } else if (left != null && right != null) {
      return root;
    } else {
      return null;
    }
  }
}

maximum path sum binary tree II

Given a binary tree in which each node contains an integer number. Find the maximum possible sum from any node to any node (the start node and the end node can be the same).

Assumptions

The root of the given binary tree is not null
public class Solution {
  public int maxPathSum(TreeNode root) {
    // Write your solution here
    int[] globalMax = new int[]{Integer.MIN_VALUE};
    maxSinglePathSum(root, globalMax);
    return globalMax[0];
  }

  private int maxSinglePathSum(TreeNode root, int[] globalMax) {
    if (root == null) {
      return 0;
    }
    int leftMax = maxSinglePathSum(root.left, globalMax);
    int rightMax = maxSinglePathSum(root.right, globalMax);
    leftMax = Math.max(leftMax, 0);
    rightMax = Math.max(rightMax, 0);
    globalMax[0] = Math.max(globalMax[0], root.key + leftMax + rightMax);
    return root.key + Math.max(leftMax, rightMax);
  }
}

Notice: Must use an int array instead of an int here for globalMax. Because primitive types (e.g., int) are passed by value, i.e. a copy of the original value; but objects (e.g., array) are passed by reference.


Next Post
Binary Search