Interview Question
Country: United States
sounds good. but the tree could have more than 2 children.
anyways not any big change needs to be made to your code.
This is a very good solution, and as mentioned above, easily modifiable to fit a tree with N children per node. To elaborate, this is a Depth First traversal of the tree that moves to the farthest children and works backwards to the root. It should visit each node exactly once, and therefor its time complexity is O(n). Given that it is a recursive function that will add a sum variable to the stack with each call, it's space complexity becomes O(n) as well.
This is a problem easily solved with dynamic programming and adapted to code, here's the subproblem formula
OPT(node x) = { x.val if x is a leaf ; else max(x.val + OPT(k)) where k cycles through all children of x
in code, and this might be a bit sloppy, and assuming all children of any node t are listed in an array of nodes called t.children, looks like:
int find_max(tree t){
if (t == NULL) return 0; //this should never be reached, but its good to be secure
int max = t.val;
for(int i = 0; i < t.children.length; i++){
int q = find_max(t.children[i]);
if(t.val + q > max) { max = t.val + q);
}
return max;
}
Additionally, to speed this up from some ugly O(2^n) answer (and that's only assuming each has two children, ick, imagine the painful slowness) we can use what is called memoization, no not memorization, memoization.
As each max value for a node is found, we store it into a caching array, then upon the next time we want to get the value for that node, instead of having to run through the recursion all over again, we can simply look it up in O(1) time, this effectively gives us a runtime of
O(n log (n))
which is substantially better and far more scalable. This also eases strain on computation in the event that children have more than one parent, or other weird tree-witchcrafty things.
We can break the problem in two steps
1) Get the leaf node for which sum is maximum
2) Once we have target leaf node, print the path from root to traget
public boolean printPath(BinaryNode node, BinaryNode target)
{
if(node == null)
{
return false;
}
if(node.equals(target) || printPath(node.left, target) || printPath(node.right, target))
{
System.out.print(node.data + "-->");
return true;
}
return false;
}
private int maxSum = 0;
private BinaryNode maxSumLeaf = null;
private void getMaxSumVodeLeaf(BinaryNode node, int currentSum)
{
if(node == null)
{
return;
}
currentSum = currentSum + node.data;
if(node.left == null && node.right == null)
{
if(currentSum >= maxSum)
{
maxSum = currentSum;
maxSumLeaf = node;
}
}
getMaxSumVodeLeaf(node.left, currentSum);
getMaxSumVodeLeaf(node.right, currentSum);
}
public int getMaxSum(BinaryNode node)
{
if(node == null)
{
return 0;
}
maxSum = 0;
maxSumLeaf = null;
getMaxSumVodeLeaf(node, 0);
return maxSum;
}
public int printMaxSumPath(BinaryNode node)
{
getMaxSum(node);
printPath(node, maxSumLeaf);
System.out.println();
return maxSum;
}
Another possible solution is
1) First find the maximum Sum
2) Then print the path which has sum = maximum sum found in first step
public void findSumPath(BinaryNode node, int currentSum, String path, int sum)
{
if (node != null)
{
currentSum = currentSum + node.data;
path = path + node.data + "-->";
if (currentSum == sum)
{
System.out.println(path);
return;
}
else if (currentSum < sum)
{
findSumPath(node.left, currentSum, path, sum);
findSumPath(node.right, currentSum, path, sum);
}
else
{
System.out.println("No such path exists");
return;
}
}
}
public int findMaxSum(BinaryNode node)
{
if (node == null)
{
return 0;
}
return (node.data + max(findMaxSum(node.left), findMaxSum(node.right)));
}
public int printMaxSum(BinaryNode node)
{
int maxSum = findMaxSum(node);
findSumPath(node, 0, "", maxSum);
System.out.println();
return maxSum;
}
private int max(int value1, int value2)
{
if (value1 >= value2)
{
return value1;
}
return value2;
}
[This will give you the actual path, it's easier to just get the sum]
Do preorder traversal (yes, you can do preorder traversal on N-ary trees too), such that when you go to a node you increment a running sum by the value at that node, and when you exit the node you subtract that value back.
When you reach a child, add that child's value to sum, and store both (key of child, sum to child) into a hash or DirectAccessTable.
So this is O(n) as it visits each node once..
At the end linear scan the table for max, and get the key of the child.
The question says paths from root to leaf nodes so there is no need to store the sum for non-leaf nodes.
Regardless any solution needs to examine paths to all leaf nodes.
If we have parent pointers the storage becomes a little less:
Rather than storing all leaf node sums we just need to maintain pointer to the leaf node with max sum. Then at the end we can follow parent pointers from the max sum leaf node up to the root to print the path.
Recursively calculate the sum
- Shiva August 30, 2013int maxsum(Node *root)
{
if (root == NULL)
{
return 0;
}
return(root->val + max(maxsum(root->left),maxsum(root->right));
}