863. All Nodes Distance K in Binary Tree

#binary-trees

Problem

Intuition

Time Complexity


O(V + E) -> BFS for marking parents
O(V + E) -> BFS for traversing from target
Worst case is that taregt is root node and the "k" is max depth of the tree

Total Time Complexity = O(V + E) + O(V + E) = 2 * O(V + E) = O(V + E)

Space Complexity

O(V + E), to store the parent child mapping

Solution

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private Map<TreeNode, TreeNode> markParents(TreeNode node) {
        // Standard BFS traversal
        Deque<TreeNode> q = new ArrayDeque<>();
        q.offer(node);

        // Create a parents map
        Map<TreeNode, TreeNode> parentMap = new HashMap<>();

        while(!q.isEmpty()) {
            // The difference in this traversal is that, we do not go level by
            // level exactly. 
            TreeNode current = q.poll();
            
            // At every node, we just check if the left subtree
            // and right subtree is null or not
            if(current.left!=null) {
                // If it is not null, then in the parent map, we just add the
                // "current left node" parent as the "current" node
                parentMap.put(current.left, current);
                q.offer(current.left);
            }

            if(current.right != null) {
                // If it is not null, then in the parent map, we just add the
                // "current right node" parent as the "current" node
                parentMap.put(current.right, current);
                q.offer(current.right);
            }
        }

        return parentMap;
    }

    public List<Integer> distanceK(TreeNode root, TreeNode target, int k) {
        // Time Complexity:
        // O(V + E) -> BFS for marking parents
        // O(V + E) -> BFS for traversing from target
        // Worst case is that taregt is root node and the "k" is max depth of the tree
        // Total Time Complexity = O(V + E) + O(V + E) = 2 * O(V + E) = O(V + E)

        // Space Complexity: O(V + E), to store the parent child mapping

        // Create a map which has information about every nodes parents
        Map<TreeNode, TreeNode> parents = markParents(root);

        // Here the traversal is not only one way i.e. bottom only, but also to top
        // So we include parent nodes whiles traversing and to make sure the 
        // node is not double processed, we create a "visited" set which keeps
        // a track of node which have been already processed
        Set<TreeNode> visited = new HashSet<>();

        // BFS traversal
        Deque<TreeNode> q = new ArrayDeque<>();
        // We directly add the target node to the queue. That will be the starting
        // point, this makes sure that we will traverse only "k" units distance from
        // the tree
        q.offer(target);
        visited.add(target);

        int currentLevel = 0;

        while(!q.isEmpty()) {
            int n = q.size();
            
            // When the current level equals to the "k", then we 
            // do not need to process anything else, so break
            if(currentLevel == k) break;

            for(int i=0;i<n;i++) {
                TreeNode current = q.poll();

                // Get the left, right and parent node
                TreeNode left = current.left;
                TreeNode right = current.right;
                TreeNode parent = parents.get(current);

                // Check if they are null or not and if they are visited or not
                if(left != null && !visited.contains(left)) {
                    // If they pass the above two conditions, then
                    // add to queue for processing
                    q.offer(left);
                    // Add to visited
                    visited.add(left);
                }

                // Do same as what was done for left subtree
                if(right != null && !visited.contains(right)) {
                    q.offer(right);
                    visited.add(right);
                }

                // Do same as what was done for left subtree
                if(parent!=null && !visited.contains(parent)) {
                    q.offer(parent);
                    visited.add(parent);
                }
            }
            // Increment the level after each level
            currentLevel++;
        }

        // Create a result container
        List<Integer> result = new ArrayList<>();

        // Once we reach the specified distance by using the property 
        // currentLevel == k
        // Then the "q" contains only the nodes which are at distance "k"
        // traverse through the queue and add the values to the result
        for(TreeNode curr: q) result.add(curr.val);
               
        return result;
    }
}

Last updated

Was this helpful?