package problems.geeks.tree;
/**
* Largest Independent Set Problem
*
* http://www.geeksforgeeks.org/largest-independent-set-problem/
*
* Given a Binary Tree, find size of the Largest Independent Set(LIS) in it. A subset of all tree nodes is an independent set if there is no edge between any two nodes of the subset.
* For example, consider the following binary tree. The largest independent set(LIS) is {10, 40, 60, 70, 80} and size of the LIS is 5.
*
* 10
* / \
* 20 30
* / \ \
* 40 50 60
* / \
* 70 80
*
* A Dynamic Programming solution solves a given problem using solutions of subproblems in bottom up manner. Can the given problem be solved using solutions to subproblems? If yes, then what are the subproblems? Can we find largest independent set size (LISS) for a node X if we know LISS for all descendants of X? If a node is considered as part of LIS, then its children cannot be part of LIS, but its grandchildren can be. Following is optimal substructure property.
*
* 1) Optimal Substructure:
* Let LISS(X) indicates size of largest independent set of a tree with root X.
*
* LISS(X) = MAX { (1 + sum of LISS for all grandchildren of X),
* (sum of LISS for all children of X) }
* The idea is simple, there are two possibilities for every node X, either X is a member of the set or not a member. If X is a member, then the value of LISS(X) is 1 plus LISS of all grandchildren. If X is not a member, then the value is sum of LISS of all children.
*
* 2) Overlapping Subproblems
* Following is recursive implementation that simply follows the recursive structure mentioned above.
*/
import java.util.*;
import adt.tree.Tree;
import adt.tree.TreeNode;
public class Q053_Largest_Independent_Set_Problem {
public static void main(String[] args) {
TreeNode root = Tree.tree8();
int res = LISS(root);
System.out.println(res);
}
// -----------------------------
// Recursion
// -----------------------------
static int LISS(TreeNode root) {
if (root == null) {
return 0;
}
// Caculate size excluding the current node
int size_excl = LISS(root.left) + LISS(root.right);
// Calculate size including the current node
int size_incl = 1;
if (root.left != null) {
size_incl += LISS(root.left.left) + LISS(root.left.right);
}
if (root.right != null) {
size_incl += LISS(root.right.left) + LISS(root.right.right);
}
// Return the maximum of two sizes
return Math.max(size_excl, size_incl);
}
// -----------------------------
// Dynamic Programming
// -----------------------------
// 1. base case:
// root == null, return 0
// root has liss, return root.liss
// root is leaf, root.liss = 1, return 1
//
// the rest is same as recursion
// root.liss = max(size_excl, size_incl)
// return root.liss
}