Microsoft Interview Question for SDE1s


Country: India




Comment hidden because of low score. Click to expand.
4
of 4 vote

With a BST we have an added advantage that we know all the nodes on the left is less than the current node and all the nodes on the right are greater than the current node.

So, while doing a DFS to search for a minLen path in a BST we actually can take informed decision at each node to either go left or right based on the remaining sum to search and hence cutting down the search space in half in average case. This will guarantee finding the minimum length path because -

1) If current node value is equal to sum and it is a leaf node than we have a complete path. If it is not a leaf then we need to find a zero sum minLen path along one of its subtrees.

2) If current node value is greater than (or equal to) the remaining sum i.e. value>=(sum-value) then we should search for new sum=(sum-value) in the left sub tree because - if a path exists in the left subtree, it must be the shorter than any possible path in the right subtree, since all nodes at left is smaller than those at right.

3) Similarly, If current node value is smaller than the remaining sum i.e. value<(sum-value) then we should search for new sum=(sum-value) in the right sub tree because - if a path exists in the right subtree, it must be the shorter than any possible path in the right subtree, since all nodes at right is greater than those at left.

So, average case complexity will be improved to O(lgn) with a complete BST. However, the worst case complexity will be O(n) in case where we have to search both left and right subtree for the remaining sum.

private int minLenSumPathBST(final TreeNode root, final int sum, final int len) {
    if (root == null) {
        return Integer.MAX_VALUE;
    }

    // find the remaining sum as we are including current node in the current path
    final int remainingSum = sum - root.key;
    // If remaining sum is zero and it is a leaf node then we found a complete path from root to a leaf.
    if (remainingSum == 0 && root.left == null && root.right == null) {
        return len + 1;
    }
    // If remaining sum is less than current node value then we search remaining in the left subtree.
    else if (remainingSum <= root.key) {
        int l = minLenSumPathBST(root.left, remainingSum, len + 1);
        // if search in left subtree fails to find such path only then we search in the right subtree
        if (l == Integer.MAX_VALUE) {
            l = minLenSumPathBST(root.right, remainingSum, len + 1);
        }

        return l;
    }
    // If remaining sum is greater than current node value then we search remaining in the right subtree.
    else {
        int l = minLenSumPathBST(root.right, remainingSum, len + 1);
        // if search in right subtree fails to find such path only then we search in the left subtree
        if (l == Integer.MAX_VALUE) {
            l = minLenSumPathBST(root.left, remainingSum, len + 1);
        }

        return l;
    }
}

- zahidbuet106 June 14, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

great solution!

- razib.nu June 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Do you really need the

if (l == Integer.MAX_VALUE) { l = minLenSumPathBST(root.right, remainingSum, len + 1); }

?

Wouldn't it be pointless to search for a number that by the definition of the BST you already know is greater than the remaining sum? Could just return Integer.MAX_VALUE or l and omit that part entirely?

- DirtyDave June 17, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Please Explain me whats the purpose of searching in the right subtree if the remaining sum is already less than the current node. As per BST, only the elements greater than should be on the right. can you explain with an example?

Say for Example, we have  a BST

				5
			3		6

And the sum we are searching for is 9, we come to root and the remaining sum will be 9 -5 = 4, then we search it in the left subtree to get the pathcount or no pathcount. We dont need to search in the right subtree since no elements greater than 5 can be present.

- deepak_gta June 23, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Consider this example, find the path for sum = 3:

3
/
-2
\
2

- zahidbuet106 June 23, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

your example will not use

if (l == Integer.MAX_VALUE) { l = minLenSumPathBST(root.right, remainingSum, len + 1);

}it goes left, then in -2 node, it goes right, then finds a solution.

I think they are right. that line can be deleted.

- Anonymous July 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Anonymous
those paths are needed. Consider for this case -

6
/ \
4 117
/ \
3 5

- zahidbuet106 December 22, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

DFS, always search the larger subtree first.
In BST, you can skip the other subtree if its value is too big. Thus the time complexity can be O(n) in best case.

- Anonymous May 30, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 4 vote

In BT we have to search every path to get the final result, because we do not know any info about subtrees. But in BST, as long as we find a path meeting the requirement we can stop the searching process:
(0)say now we encounter node p, with its value being p->value, then we perform targetSum -= p->value.
(1)If targetSum < 0 now
our first choice would be going on with the left subtree, because:
if a path exists along the left subtree, it must be shorter than any possible path along the right, since all nodes at left is smaller than those at right.
If there is no such path along the left, then we check p->value, if it is negative, then we go on searching right subtree,
else we stop current searching because all nodes at right(larger than p->value) is positive, which can not have a negative sum.
(2)If targetSum > 0 now
similar with (1), yet our first choice would be going on with right subtree, because:
if the path exists along the right subtree, it must be shorter than any possible path along the left, since all nodes at right is greater than those at left.
If there is no such path along the right, then we check p->value, if it is positive, then we go on searching left subtree,
else we stop current searching because all nodes at left(smaller than p->value) is negative, which can not have a positive sum.
(3)If targetSum = 0 now
if p is not a leaf, then current path is a dead end, no need to search deeper;
else the shortest path is found!
Following is code in C++:

struct TreeNode
{
	int value;
	TreeNode* left;
	TreeNode* right;
};
int getShortestPathWithSumInBST(TreeNode* root, int sum)
{
	if(root == NULL) return -1;

	int res;
	if(helper(root, sum, 0, res)) return res;
	return -1;
}
bool helper(TreeNode* p, int sum, int prevLen, int& res)
{
	sum -= p->value;
	++prevLen;
	if(sum < 0){
		return p->left != NULL && helper(p->left, sum, prevLen, res) ||
	    	   p->value < 0 && p->right != NULL && helper(p->right, sum, prevLen, res);
	}
	else if(sum > 0){
	    return p->right != NULL && helper(p->right, sum, prevLen, res) ||
	    	   p->value > 0 && p->left != NULL && helper(p->left, sum, prevLen, res);
	}
	else{
		if(p->left != NULL || p->right != NULL) return false;
		res = prevLen;
		return true;
	}
}

- uuuouou May 30, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Assume sum = 3 and the BST is as below, we should keep searching but not return false

3
/
-2
\
2

- solongso June 03, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

yes. only a little modification is needed to handle the cases like one described by solongso in the previous comment

- zahidbuet106 June 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

With a BST we have an added advantage that we know all the nodes on the left is less than the current node and all the nodes on the right are greater than the current node.

So, while doing a DFS to search for a minLen path in a BST we actually can take informed decision at each node to either go left or right based on the remaining sum to search and hence cutting down the search space in half in average case. This will guarantee finding the minimum length path because -

1) If current node value is equal to sum and it is a leaf node than we have a complete path. If it is not a leaf then we need to find a zero sum minLen path along one of its subtrees.

2) If current node value is greater than (or equal to) the remaining sum i.e. value>=(sum-value) then we should search for new sum=(sum-value) in the left sub tree because - if a path exists in the left subtree, it must be the shorter than any possible path in the right subtree, since all nodes at left is smaller than those at right. If the search in left subtree return with no such path then will search in the right subtree if only if the value of current node is.

3) Similarly, If current node value is smaller than the remaining sum i.e. value<(sum-value) then we should search for new sum=(sum-value) in the right sub tree because - if a path exists in the right subtree, it must be the shorter than any possible path in the right subtree, since all nodes at right is greater than those at left. If the search in right subtree returns with no such path only then will search in the left subtree.

So, average case complexity will be improved to O(lgn) with a complete BST. However, the worst case complexity will be O(n) in case where we have to search both left and right subtree for the remaining sum.

private int minLenSumPathBST(final TreeNode root, final int sum, final int len) {
    if (root == null) {
        return Integer.MAX_VALUE;
    }

    // find the remaining sum as we are including current node in the current path
    final int remainingSum = sum - root.key;
    // If remaining sum is zero and it is a leaf node then we found a complete path from root to a leaf.
    if (remainingSum == 0 && root.left == null && root.right == null) {
        return len + 1;
    }
    // If remaining sum is less than current node value then we search remaining in the left subtree.
    else if (remainingSum <= root.key) {
        int l = minLenSumPathBST(root.left, remainingSum, len + 1);
        // if search in left subtree fails to find such path only then we search in the right subtree
        if (l == Integer.MAX_VALUE) {
            l = minLenSumPathBST(root.right, remainingSum, len + 1);
        }

        return l;
    }
    // If remaining sum is greater than current node value then we search remaining in the right subtree.
    else {
        int l = minLenSumPathBST(root.right, remainingSum, len + 1);
        // if search in right subtree fails to find such path only then we search in the left subtree
        if (l == Integer.MAX_VALUE) {
            l = minLenSumPathBST(root.left, remainingSum, len + 1);
        }

        return l;
    }
}

- zahidbuet106 June 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

This the Java version inspired by uuuouou. Thanks.

public class Test{
	public class Node{
		int value;
		Node left;
		Node right;
		
		public Node(int value){
			this.value = value;
			this.left = null;
			this.right = null;
		}
	}
	
	public int findMinimumLength(Node root, int rest){
		if(root == null){
			return Integer.MAX_VALUE;
		}
		rest -= root.value;
		int minValue = Integer.MAX_VALUE;
		//if rest is less than 0, then if we go to left child, we may be faster since all
		//the values in the left subtree are less than that in the right subtree.
		if(rest < 0){
			if(root.left != null){
				int value = findMinimumLength(root.left, rest);
				minValue = Math.min(minValue, value);
			}
			if(minValue == Integer.MAX_VALUE && root.right != null){
				minValue = Math.min(minValue, findMinimumLength(root.right, rest));
			}
		}else if(rest > 0){//same thing with right tree.
			if(root.right != null){
				int value = findMinimumLength(root.right, rest);
				minValue = Math.min(minValue, value);
			}
			if(minValue == Integer.MAX_VALUE && root.left != null){
				minValue = Math.min(minValue, findMinimumLength(root.left, rest));
			}
		}else{//find the sum and this node is the leaf node.
			if(root.left == null && root.right == null){
				minValue = 0;
			}
		}
		//try to avoid integer overflow
		if(minValue == Integer.MAX_VALUE){
			return Integer.MAX_VALUE;
		}else{
			return minValue + 1;
		}
	}
	
	public static void main(String[] args){
		Test test = new Test();
		
		Node root = test.new Node(10);
		root.left = test.new Node(2);
		root.right = test.new Node(5);
		root.left.left = test.new Node(3);
		
		System.out.println(test.findMinimumLength(root, 15));
		
	}
}

- ravio May 30, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

hey

play.google.com/store/apps/details?id=com.couponkart.couponcodes

try this out . might be useful

- Anonymous June 01, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

For a general tree:

static int minlen=Integer.MAX_VALUE;
public int minRootToLeafPathLength(TreeJ root,int len,int Sum, int val){
		if(root==null){
			return 0;
		}
		int p=val+Integer.parseInt(root.val.toString());
		if(p==Sum && (root.left==null && root.right==null)){
			if(len<minlen){
				minlen=len+1;
			}
		}
		minRootToLeafPathLength(root.right,len+1,Sum,p);
		minRootToLeafPathLength(root.left,len+1,Sum,p);
		
		return minlen;
	}

Call this: System.out.println(tf.minRootToLeafPathLength(root, 0, 21, 0));
Create tree:

public void makeSimpleTree(){
		root=new TreeJ<Integer>(5);
		root.right=new TreeJ<Integer>(6);
    	root.right.left=new TreeJ<Integer>(2);
		root.right.right=new TreeJ<Integer>(4);
		root.right.right.left=new TreeJ<Integer>(7);
		root.right.right.left.right=new TreeJ<Integer>(1);
		
		root.left=new TreeJ<Integer>(8);
		root.left.left=new TreeJ<Integer>(5);
		root.left.right=new TreeJ<Integer>(4);
		root.left.left.left=new TreeJ<Integer>(3);
		root.left.right.left=new TreeJ<Integer>(6);
		
	}

- abhishek June 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

int find_sum(Item* root, sum) {
  if (!root && !sum)
    return 0;
  if (!root || root->i > sum)
    return -1;
  int new_sum = sum - root->i;
  int rs = -1;
  if (new_sum > root->i)
    rs = find_sum(root->right, new_sum);
  if (rs == -1)
    find_sum(root->left, new_sum);
  return rs + 1;
}

- zprogd June 30, 2014 | Flag Reply


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More