Facebook Interview Question for SDE1s


Country: United States




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

The leaf need not be necessary a descendant of the target node.The path to nearest leaf can go through the parent of the target node also.We need to consider all such scenarios.

- koustav.adorable July 26, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

If u have a parent pointer it's really simple, from a node go up, left and right (put those nodes into a queue as pairs of current: enqueued((self, self.left)), ...
Then if u dequeue only visit those that are not equal to the first element taken from the queue (don't go back where I came from).
Then the first leave encountered is it...

If u have no parent pointer, u create first a parent-pointer list, from the root to the node u start from, all other parent pointers are not needed.

Code follows...

- Chris July 26, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

the idea is to do a special kind of BFS:
1) I assume I have a parent pointer for each node, if I don't I can
easily get a dictionary with necessary parent pointers, which is
derived from the path from the tree root to the node given
(I need the root then, that defines the tree I can look in)
Further I assume that if I get passed a leaf I should return the
nearest leaf and not the passed in node (leaf).
2) Instead of maintaining visited array, I can simply not go
back where I came from because there are no cycles and no
forward edges in a regular binary tree
3) I just start at a node and go to the parent, left and right
...

Sample tree

p      
       / \
      h   q
    /   \
   c     k
 /  \     \
b    e     m
          /
         p

complete implementation using parent pointers for simplicity
in python 3:

from collections import deque

def find_nearest_leaf(node):
    queue = deque()
    queue.append((0, None, node))
    while queue:
        dist, prev, cur = queue.popleft()
        if dist > 0 and cur.is_leaf():
            return (cur, dist)
        for adj in [cur.parent, cur.left, cur.right]:
            if adj is not None and adj != prev:
                queue.append((dist + 1, cur, adj))
        return (None, None)
    
class Node:
    def __init__(self, value, left=None, right=None):
        self.parent = None
        self.left = left
        self.right = right
        self.value = value
        if self.right is not None:
            self.right.parent = self
        if self.left is not None:
            self.left.parent = self

    def is_leaf(self): 
        return self.right is None and self.left is None
    
node_h = Node('h', Node('c', Node('b'), Node('e')), Node('K', None, Node('m', Node('p'), None)))
Node('p', node_h, Node('q'))
print(find_nearest_leaf(node_h)) # return 2

- Chris July 26, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Thanks for clarifying the problem to me, now the prototype makes perfect sense and also why there can take more than O(n).
I have came up with the following algorithm.
The distance to the closest leaf is the minimum from the next three possible values: the distance from the current node to a leaf, the distance of father of the current node to a leaf or the distance from the current node to the root and from the others root child to a leaf. This algorithm runs in O(n). Code in Python

class node:
    def __init__(self, value):
        self.value = value
        self.left = self.right = None


def compute_distance_between_nodes(n1, n2):
    if n1 == None: return None

    frontier = [(n1, 0, None)]
    while frontier:
        current_node, distance, last = frontier.pop()
        if current_node == n2:
            return (distance + 1, last)
        if current_node.left:
            frontier.append((current_node.left, distance + 1, current_node))
        if current_node.right:
            frontier.append((current_node.right, distance + 1, current_node))

    return None

def least_height(node):
    if node == None:
        return 0
    else:
        return min(tree_height(node.left), tree_height(node.right)) + 1

def closest_leaf(root, target):
    if root == target:
        return least_height(root)

    found_left_side = True
    a = compute_distance_between_nodes(root.left, target)
    if not a:
        found_left_side = False
        a = compute_distance_between_nodes(root.right, target)
    distance_to_root, last_node = a

    distance_from_root = least_height(root.left) if found_left_side else least_height(root.right)
    distance_from_last_node = least_height(last_node)
    return min(least_height(target), distance_to_root + distance_from_root, distance_from_last_node + 1)

Edit: Apologies for not coding what the question states. The idea of returning a tuple with the node and the distance will work

- Fernando July 27, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

since the problem was changed to no parent pointers, here the described approach without parent pointers

# solution without parent pointer
from collections import deque

# searches the tree from the root to the node in O(n) time
# and returns the path to the node as a dictionary (key=node, value=parent)
def find_path_to_node(root, node):
    path = {}
    stack = [[False, root, None]]
    while stack:        
        visited, root, parent = stack[-1]
        if visited:
            stack.pop()
            del path[root]
        else:
            stack[-1][0] = True
            path[root] = parent
            if root == node:
                break # found node
            for child in [root.left, root.right]:
                if child is not None:
                    stack.append([False, child, root])
    return path

# does the find in O(n) time
def find_nearest_leaf(root, node):
    parents = find_path_to_node(root, node)
    queue = deque()
    queue.append((0, None, node))
    while queue:
        dist, prev, cur = queue.popleft()
        # if is it a leaf and not the node I started at, finished
        if dist > 0 and cur.is_leaf():
            return dist
        for adj in [parents.get(cur), cur.left, cur.right]:
            if adj is not None and adj != prev:
                queue.append((dist + 1, cur, adj))
    
class Node:
    def __init__(self, value, left=None, right=None):
        self.left = left
        self.right = right
        self.value = value

    def is_leaf(self): 
        return self.right is None and self.left is None
    
node_h = Node('h', Node('c', Node('b'), Node('e')), Node('K', None, Node('m', Node('p'), None)))
root = Node('p', node_h, Node('q'))
print(find_nearest_leaf(root, node_h)) # return 2

- Chris July 28, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public int closestLeaf(Node node, Node root){
       //Closest leaf is the min of 1. Closest leaf in subtree rooted at given node and 2. 1 + closest leaf in parents subtree
        //Find the closest leaf among given nodes children
        int closestNodeChild = closestLeafChild(node);

        //Find parent of this node in O(N) time        
        Node parent = findParent(node, root);
        int closestParentChild = closestLeafChild(parent);

        return Math.min(closestNodeChild, 1 + closestParentChild);
    }

    private Node findParent(Node node, Node root){
        if(root == null || root == node) return null;
        if(root.left == node || root.right == node){
            return root;
        }
        Node left = findParent(node, root.left);
        Node right = findParent(node, root.right);
        if(left != null) return left;
        if(right != null) return right;
        return null;
    }

    private int closestLeafChild(Node root){
        if(root == null) return 0;
        return 1 + Math.min(closestLeafChild(root.left), closestLeafChild(root.right));
    }

- tomahawk August 07, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

All you need to do is find the distance to the target node and distance to the nearest leaf node add the distance for each node return the leaf node which had the sum to be the min.

- Shubh October 19, 2018 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

A simple BFS using queue should do the job. If a node has no children to be added to the queue, we have reached the solution.

- krupen.ghetiya July 26, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

I don't understand the question. As stated the closest leaf can be computed as a variation of the height of a tree, but instead of taking the maximum possible height taking the minimum height. That algorithm takes O(n) in relation with the number of nodes (in the worst case you only visit each node once). Also doesn't match the prototype of the function, you only need one node to compute the distance to the leaf. Why the root??.
Code in python

class node:
    def __init__(self, value):
        self.value = value
        self.left = self.right = None

def closest_leaf(node):
    if node == None:
        return 0
    else:
        return min(tree_height(node.left), tree_height(node.right)) + 1

Note: You can return a tuple with the node and the height in case you are interested on the node as the problem states.

- Fernando July 26, 2017 | 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