January 05, 2020

863. All Nodes Distance K in Binary Tree

863. All Nodes Distance K in Binary Tree

Similar questions:

树的遍历只有从parent到children的单向关系。但是题目需要找出从target node到parent和children距离为K的nodes, 所以需要有方法记录从child到parent的关系,可以从树构建双向图(邻接链表),或者另外记录child到parent的反向连接。

参考了这个讲解这个视频讲解.

Sol 1. Build Graph + BFS

  1. Build bidirected graph (using hashmap represented Adjacency list)
  2. BFS traversal

Time complexity: O(n), Space complexity: O(n)

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
        List<Integer> res = new ArrayList<>();
        if (root == null || K < 0) {
            return res;
        }
        Map<TreeNode, List<TreeNode>> map = new HashMap<>();
        buildGraph(root, null, map);
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(target);
        // int step = 0;
        Set<TreeNode> visited = new HashSet<>();
        visited.add(target);
        while (!queue.isEmpty()) {
            int size = queue.size();
            if (K == 0) {
                for (int i = 0; i < size; i++) {
                    res.add(queue.poll().val);
                }
                return res;
            }
            for (int i = 0; i < size; i++) {
                TreeNode node = queue.poll();
                for (TreeNode next : map.get(node)) {
                    if (visited.contains(next)) {
                        continue;
                    }
                    visited.add(next);
                    queue.offer(next);
                }
            }
            K--;
        }
        return res;
    }
    
    private void buildGraph(TreeNode node, TreeNode parent, Map<TreeNode, List<TreeNode>> map) {
        if (node == null) {
            return;
        }
        if (!map.containsKey(node)) {
            map.put(node, new ArrayList<>());
            if (parent != null) {
                map.get(node).add(parent);
                map.get(parent).add(node);
            }
            buildGraph(node.left, node, map);
            buildGraph(node.right, node, map);
        }
    }
}

Sol 2. DFS

  1. Build child-parent relationship (using hashmap)
  2. DFS
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        Map<TreeNode, TreeNode> map = new HashMap<>();
        findParent(root, null, map);
        Set<TreeNode> visited = new HashSet<>();
        helper(target, K, map, visited, res);
        return res;
    }
    
    private void helper(TreeNode node, int K, Map<TreeNode, TreeNode> map, Set<TreeNode> visited, List<Integer> res) {
        if (visited.contains(node)) {
            return;
        }
        visited.add(node);
        if (K == 0) {
            res.add(node.val);
            return;
        }
        if (node.left != null) {
            helper(node.left, K - 1, map, visited, res);
        }
        if (node.right != null) {
            helper(node.right, K - 1, map, visited, res);
        }
        if (map.containsKey(node)) {
            helper(map.get(node), K - 1, map, visited, res);
        }
    }
    
    private void findParent(TreeNode node, TreeNode parent, Map<TreeNode, TreeNode> map) {
        if (node == null) {
            return;
        }
        if (node.left != null) {
            map.put(node.left, node);
        }
        if (node.right != null) {
            map.put(node.right, node);
        }
        findParent(node.left, node, map);
        findParent(node.right, node, map);
    }
}

Sol 3. Recursion

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    private List<Integer> res = new ArrayList<>();
    public List<Integer> distanceK(TreeNode root, TreeNode target, int K) {
        dis(root, target, K);
        return res;
    }
    
    // distance from root to target; returns -1 if target is not in the tree
    private int dis(TreeNode root, TreeNode target, int K) {
        if (root == null) {
            return -1;
        }
        if (root == target) {
            collect(target, K);
            return 0;
        }
        int left = dis(root.left, target, K);
        int right = dis(root.right, target, K);
        
        // Target in the left subtree
        if (left >= 0) {
            if (left == K - 1) {
                res.add(root.val); 
            }
            collect(root.right, K - left - 2);
            return left + 1;
        }
        
        // Target in the right subtree
        if (right >= 0) {
            if (right == K - 1) {
                res.add(root.val);
            }
            collect(root.left, K - right - 2);
            return right + 1;
        }
        return -1;
    }
    
    // Collect nodes that are d steps from root
    private void collect(TreeNode root, int d) {
        if (root == null || d < 0) {
            return;
        }
        if (d == 0) {
            res.add(root.val);
        }
        collect(root.left, d - 1);
        collect(root.right, d - 1);
    }
}
comments powered by Disqus