LeetCode 236. Lowest Common Ancestor of a Binary Tree

LCA problem, a really classic one. so you must really understand this problem.

but for this kind of problem, it doesn’t looks like it can be solved in recursion or simple traverse.

public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q)
so in order to solve this problem, we should know that each node might have many child nodes(children or grandchildren, doesn’t matter), so if we can find those two nodes in a node’s child node poll, and this node have the max depth, then it’s the LCA of two given nodes.

but how to get all those? so for this kind of problem, it’s easy for us to trapped into a cycle that this can be solved in a simpler way. but actually it’s not.
so the generate idea to solve this problem will be:
we use hashmap to store the child-parent relationship so if we need to trace back, then we can just trace all the way back.
and we use preorder dfs to iterate every node and construct our map.
now since the map contains those two nodes and the way, so we trace back all the way back, and first we need to keep record of all the parent/grad…till root of p or q, becase each node might be the ancester. and then we traceback starting from q or p, then the first node that is already in that set is the LCA, which is our final answer

Even though above paragraph looks kind of verbose, but it’s very easy understanding.
and the implement will be:

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q) return root;
        
        LinkedList<TreeNode> stack = new LinkedList<>();
        HashMap<TreeNode, TreeNode> parent = new HashMap<>();
        parent.put(root, null); //node and it's direct parent node
        stack.push(root);
        
        while (!((parent.containsKey(p)) && (parent.containsKey(q)))) { //when we found p and q, then we can stop this preorder dfs
            TreeNode cur = stack.pop();
            if (cur.left != null) {
                stack.push(cur.left);
                parent.put(cur.left, cur);
            }
            if (cur.right != null) {
                stack.push(cur.right);
                parent.put(cur.right, cur);
            }
        }
        //now since the map contains those two nodes and the way, so we trace back all the way back, and first we need to keep record of all the parent/grad...till root of p or q, becase each node might be the ancester. and then we traceback starting from q or p, then the first node that is already in that set is the LCA, which is our final answer
        HashSet<TreeNode> set = new HashSet<>();
        TreeNode cur = p;
        while (cur != root) {
            set.add(cur);
            cur = parent.get(cur);
        }
        TreeNode cur2 = q;
        while (cur2 != root) {
            if (set.contains(cur2)) {
                return cur2;
            }
            cur2 = parent.get(cur2);
        }
        return root;
               
    }
}
posted @ 2020-11-17 10:49  EvanMeetTheWorld  阅读(13)  评论(0)    收藏  举报