WalzoneInterview Prep
📞 Interviewing soon? Practice with a realistic AI mock phone interview — it calls you, then scores you. First 15 min FREE →

Dynamic Programming · Advanced · question 49 of 100

Solve the problem of finding the Largest Independent Set (LIS) in a binary tree using dynamic programming.?

📕 Buy this interview preparation book: 100 Dynamic Programming questions & answers — PDF + EPUB for $5

The Largest Independent Set (LIS) of a binary tree is defined as the largest subset of nodes in the tree such that no two nodes in the subset have an edge connecting them. In other words, the LIS is the largest set of nodes that can be selected from the tree in such a way that no two selected nodes are adjacent.

The dynamic programming approach to solve this problem involves recursively computing the LIS of each subtree of the binary tree, and then combining these results to obtain the LIS of the entire tree.

We can define a function LIS(node) which returns the size of the LIS of the subtree rooted at the given node. The function can be defined recursively as follows:

- If the given node is a leaf, the LIS is 1.

- If the given node is not selected, we can compute the LIS of its children and return the sum of these values.

- If the given node is selected, we cannot select any of its children. Instead, we must compute the LIS of its grandchildren (the children of its children) and return the sum of these values plus one.

By using memoization (storing intermediate results), we can avoid recomputing the LIS of each subtree multiple times. The memoization table can be implemented using a HashMap, with the tree nodes as keys and the LIS values as values.

Here’s a Java implementation of this approach:

import java.util.*;

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;
    TreeNode(int x) { val = x; }
}

class LISBinaryTree {
    Map<TreeNode, Integer> memo = new HashMap<>();
    
    public int largestIndependentSet(TreeNode root) {
        if (root == null) return 0;
        if (memo.containsKey(root)) return memo.get(root);
        
        int size = 0;
        // compute LIS excluding root
        size += largestIndependentSet(root.left);
        size += largestIndependentSet(root.right);
        // compute LIS including root
        if (root.left != null) {
            size += largestIndependentSet(root.left.left);
            size += largestIndependentSet(root.left.right);
        }
        if (root.right != null) {
            size += largestIndependentSet(root.right.left);
            size += largestIndependentSet(root.right.right);
        }
        int lis = Math.max(size + 1, largestIndependentSet(root.left) + largestIndependentSet(root.right));
        memo.put(root, lis);
        return lis;
    }
}

We start by initializing a memoization table using a HashMap. The ‘largestIndependentSet‘ function takes a binary tree node as input, and recursively computes the LIS of the subtree rooted at that node using the memoization table to avoid recomputing values.

The size of the subtree LIS is computed by recursively calling ‘largestIndependentSet‘ on the left and right child nodes, adding their return values, and adding the size of the LIS of the grandchildren of the root, if any. If the root is included in the LIS, we return the sum of the sizes of the grandchildren plus one. Otherwise, we return the maximum LIS excluding the root and the LIS including the root.

Finally, we look up the LIS of the root in the memoization table. If it is present, we return it. Otherwise, we add it to the memoization table and return it.

Reading is step one. Saying it out loud is the interview. Our AI interviewer calls your phone and runs a realistic Dynamic Programming interview — then scores it.
📞 Practice Dynamic Programming — free 15 min
📕 Buy this interview preparation book: 100 Dynamic Programming questions & answers — PDF + EPUB for $5

All 100 Dynamic Programming questions · All topics