Tuesday, October 27, 2015

Leetcode: Serialize and Deserialize Binary Tree

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
For example, you may serialize the following tree
    1
   / \
  2   3
     / \
    4   5
as "[1,2,3,null,null,4,5]", just the same as how LeetCode OJ serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Note: Do not use class member/global/static variables to store states. Your serialize and deserialize algorithms should be stateless.
Credits:
Special thanks to @Louis1992 for adding this problem and creating all test cases.


Update on 1/28/16:
BFS by removing the trailing "null" node strings.
One advantage of using BFS is we could safely removing the trailing last-level null nodes represented by the "#," string. This can save about half space (The # nodes in last-level of a binary tree is around half of the total number of trees). 

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if (root == null) {
            return "";
        }
        
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);
        
        StringBuffer sb = new StringBuffer();
        
        while (!queue.isEmpty()) {
            TreeNode curr = queue.poll();
            if (curr != null) {
                sb.append(curr.val + ",");
                queue.offer(curr.left);
                queue.offer(curr.right);
            } else {
                sb.append("#" + ",");
            }
        }
        
        // Remove the trailing #
        String result = sb.toString();
        int j = result.length() - 1;
        
        while (j > 0 && result.charAt(j) == ',' && result.charAt(j) == '#') {
            j -= 2;
        }
        
        result = result.substring(0, j);
        return sb.toString();
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if (data == null || data.length() == 0) {
            return null;
        }
        
        Queue<TreeNode> queue = new LinkedList<>();
        String[] nodes = data.split(",");
        
        TreeNode root = new TreeNode(Integer.parseInt(nodes[0]));
        queue.offer(root);
        int i = 1;

        while (!queue.isEmpty() && i < nodes.length) {
            TreeNode curr = queue.poll();
            if (nodes[i].equals("#")) {
                curr.left = null;
            } else {
                TreeNode leftNode = new TreeNode(Integer.parseInt(nodes[i]));
                curr.left = leftNode;
                queue.offer(leftNode);
            }
            
            i++;
            if (i >= nodes.length) {
                break;
            }
            
            // right node
            if (nodes[i].equals("#")) {
                curr.right = null;
            } else {
                TreeNode rightNode = new TreeNode(Integer.parseInt(nodes[i]));
                curr.right = rightNode;
                queue.offer(rightNode);
            }
            
            i++;
        }
        
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

DFS solution with using a Deque:
We can also solve the problem by using pre-order traversal of the binary tree. We need to use a deque because each time we need to remove one element from the top. Else we need to maintain a global index pointing to the current element we want to add into the tree.

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Codec {

    // Encodes a tree to a single string.
    public String serialize(TreeNode root) {
        if (root == null) {
            return "";
        }
        
        StringBuffer sb = new StringBuffer();
        serializeHelper(root, sb);
        
        return sb.toString();
    }
    
    private void serializeHelper(TreeNode root, StringBuffer sb) {
        if (root == null) {
            sb.append("#");
            sb.append(",");
            return;
        }
        
        sb.append(root.val + ",");
        serializeHelper(root.left, sb);
        serializeHelper(root.right, sb);
    }

    // Decodes your encoded data to tree.
    public TreeNode deserialize(String data) {
        if (data == null || data.length() == 0) {
            return null;
        }
        
        String[] strs = data.split(",");
        Deque<String> deque = new LinkedList<>(Arrays.asList(strs));
        
        return deserializeHelper(deque);
    }
    
    private TreeNode deserializeHelper(Deque<String> deque) {
        if (deque.isEmpty()) {
            return null;
        }
        
        String node = deque.removeFirst();
        if (node.equals("#")) {
            return null;
        }
        
        TreeNode root = new TreeNode(Integer.parseInt(node));
        root.left = deserializeHelper(deque);
        root.right = deserializeHelper(deque);
        
        return root;
    }
}

// Your Codec object will be instantiated and called as such:
// Codec codec = new Codec();
// codec.deserialize(codec.serialize(root));

Another DFS without using a Deque, but a global index.
public class Solution2 {
    public String serialdfs(TreeNode root) {
        if (root == null) {
            return "";
        }
        
        StringBuilder sb = new StringBuilder();
        
        serialdfsHelper(root, sb);
        
        return sb.toString();
    }
    
    private void serialdfsHelper(TreeNode root, StringBuilder sb) {
        if (root == null) {
            sb.append("#");
            return;
        }
        
        sb.append(root.val);
        
        serialdfsHelper(root.left, sb);
        serialdfsHelper(root.right, sb);
    }
    
    public int i = 0;
    public TreeNode deserialdfs(String s) {
        if (s == null || s.length() == 0) {
            return null;
        }
        
        return deserialdfsHelper(s);
    }
    
    private TreeNode deserialdfsHelper(String s) {
        if (i >= s.length() || s.charAt(i) == '#') {
            return null;
        }
        
        TreeNode root = new TreeNode(s.charAt(i) - '0');
        i++;
        root.left = deserialdfsHelper(s);
        i++;
        root.right = deserialdfsHelper(s);
        
        return root;
    }
    
    public static void main(String[] args) {
      Solution2 sol = new Solution2();

      TreeNode root = new TreeNode(1);
      root.left = new TreeNode(2);
      root.right = new TreeNode(3);
      root.left.left = new TreeNode(4);
      root.left.right = new TreeNode(5);


      String result = sol.serialdfs(root);
      
      TreeNode root2 = sol.deserialdfs(result);

      String result2 = sol.serialdfs(root2);

      System.out.println(result2);
    }
}

Compare between DFS and BFS:
I would like more BFS because BFS sometimes can save more space. For example,
      1
    /    \
   2    3
  / \    / \
 4 #  #  #
 / \ 
# #

By BFS: the serialized tree is 1,2,3,4
By DFS, the serialized tree is 1,2,4,#,#,#,3, which needs more space to store. 

Sunday, October 11, 2015

Leetcode: Binary Tree Upside Down

Given a binary tree where all the right nodes are either leaf nodes with a sibling (a left node that shares the same parent node) or empty, flip it upside down and turn it into a tree where the original right nodes turned into left leaf nodes. Return the new root.
For example:
Given a binary tree {1,2,3,4,5},
    1
   / \
  2   3
 / \
4   5
return the root of the binary tree [4,5,2,#,#,3,1].
   4
  / \
 5   2
    / \
   3   1  
confused what "{1,#,2,3}" means? > read more on how binary tree is serialized on OJ.
Recursive solution:
The recursive solution could be bottom-up. Note that we need a parent node to save the node's parent. Also we use the return value just to store the new node. 

这个题的关键是反转以后的binary tree 的 root 是以前二叉树的 最左边的 leaf node. 利用这个性质,我们先一路走到最左边的那个leaf node, 并且记录一下当前节点和之前的parent node。找到这个节点以后,利用返回值一直把这个点传回来。在back tracking 的过程中,当前root 的 left child 是 parent.right. (注意要判断parent 是否为null)。如果parent == null, root.left = null; 如果没有这一句,树里面就有一个环!!root.right = parent

这个题的思路比较类似reverse linked list in recursive way. 

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode upsideDownBinaryTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        
        return upsideDownBinaryTreeHelper(root, null);
    }
    
    private TreeNode upsideDownBinaryTreeHelper(TreeNode root, TreeNode parent) {
        if (root == null) {
            return parent;
        }
        
        TreeNode newNode = upsideDownBinaryTreeHelper(root.left, root);
        
        root.left = parent == null ? null : parent.right;
        root.right = parent;
        
        return newNode;
    }
}

Iterative solution:
这个属于自顶向下的方法。需要注意的是在向下走的过程中parent 其实已经被更新了,所以p.left 就不能指向parent.right, 因为 parent.right 已经在向下遍历的过程里面丢了!所以需要保存这个parent.right 这个node. 

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode upsideDownBinaryTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        
        TreeNode parent = null;
        TreeNode parentRightChild = null;
        TreeNode p = root;
        
        while (p != null) {
            TreeNode next = p.left;
            p.left = parentRightChild;
            parentRightChild = p.right;
            
            p.right = parent;
            
            parent = p;
            p = next;
        }
        
        return parent;
    }
}


Tuesday, September 8, 2015

Leetcode: Count Univalue Subtrees

Given a binary tree, count the number of uni-value subtrees.
A Uni-value subtree means all nodes of the subtree have the same value.
For example:
Given binary tree,
              5
             / \
            1   5
           / \   \
          5   5   5
return 4.
Understand the problem:
The problem can be solved by divide-and-conquer. The only trick is to use different return values to mark different cases. 
Integer.MIN_VALUE -- Mark the subtree is not univaled. 
Integer.MAX_VALUE -- Mark if the root is null. 

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    private int count = 0;
    public int countUnivalSubtrees(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        countUnivalSubtreesHelper(root);
        
        return count;
    }
    
    private int countUnivalSubtreesHelper(TreeNode root) {
        if (root == null) {
            return Integer.MAX_VALUE;
        }
        
        // Divide
        int left = countUnivalSubtreesHelper(root.left);
        int right = countUnivalSubtreesHelper(root.right);
        
        // left and right are all empty
        if (left == Integer.MAX_VALUE && right == Integer.MAX_VALUE) {
            count++;
            return root.val;
        } else if (left == Integer.MAX_VALUE || right == Integer.MAX_VALUE) {
            if (root.val == left || root.val == right) {
                count++;
                return root.val;
            } else {
                return Integer.MIN_VALUE;
            }
        } else {
            if (root.val == left && root.val == right) {
                count++;
                return root.val;
            } else {
                return Integer.MIN_VALUE;
            }
        }
    }
}

Wednesday, September 2, 2015

Leetcode: Lowest Common Ancestor of a Binary Search Tree

Given a binary search tree (BST), find the lowest common ancestor (LCA) of two given nodes in the BST.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
        _______6______
       /              \
    ___2__          ___8__
   /      \        /      \
   0      _4       7       9
         /  \
         3   5
For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6. Another example is LCA of nodes 2 and 4 is 2, since a node can be a descendant of itself according to the LCA definition.
Understand the problem:
The problem can be solved by either treating the BST as a regular binary tree, or BST. 
For the binary tree solution, we could check out the previous post using divide and conquer solution. 

Now let's take a look at the solution for BST.

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null) {
            return root;
        }
        
        if (root.val > p.val && root.val < q.val) {
            return root;
        } else if (root.val > p.val && root.val > q.val) {
            return lowestCommonAncestor(root.left, p, q);
        } else if (root.val < p.val && root.val < q.val) {
            return lowestCommonAncestor(root.right, p, q);
        }
        
        return root;
    }
}

Update on 1/27/16:
I think this solution is clearer in the sense that we need to make sure node p and always at left of q.
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || p == null || q == null) {
            return null;
        }
        
        // Make sure p is on the left of q
        if (p.val > q.val) {
            TreeNode temp = p;
            p = q;
            q = temp;
        }
        
        if (root.val >= p.val && root.val <= q.val) {
            return root;
        } else if (root.val > p.val && root.val > q.val) {
            return lowestCommonAncestor(root.left, p, q);
        } else {
            return lowestCommonAncestor(root.right, p, q);
        }
    }
}

Tuesday, September 1, 2015

Leetcode: Invert Binary Tree

Invert a binary tree.
     4
   /   \
  2     7
 / \   / \
1   3 6   9
to
     4
   /   \
  7     2
 / \   / \
9   6 3   1
Trivia:
This problem was inspired by this original tweet by Max Howell:
Google: 90% of our engineers use the software you wrote (Homebrew), but you can’t invert a binary tree on a whiteboard so fuck off.
Understand the problem:
The problem is very easy to understand. Just to re-link root's left child to the right sub-tree, and root's right child to the left sub-tree. Only one thing to note is we must use a temp Node when we do the swap. 

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode invertTree(TreeNode root) {
        if (root == null) {
            return null;
        }
        
        TreeNode temp = root.left;
        
        root.left = invertTree(root.right);
        root.right = invertTree(temp);
        
        return root;
    }
}

A BFS Solution:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode invertTree(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        if (root == null) {
            return null;
        }
        
        queue.offer(root);
        
        while (!queue.isEmpty()) {
            TreeNode curr = queue.poll();
            
            if (curr.left != null) {
                queue.offer(curr.left);
            }
            
            if (curr.right != null) {
                queue.offer(curr.right);
            }
            
            TreeNode temp = curr.left;
            curr.left = curr.right;
            curr.right = temp;
        }
        
        return root;
    }
}

Leetcode: Count Complete Tree Nodes

Given a complete binary tree, count the number of nodes.
Definition of a complete binary tree from Wikipedia:
In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
Understand the problem:
First of all, what is a complete binary tree? 
A complete binary tree is a binary tree where each level except for the last level is full. 

A naive solution:
A naive solution is just to traverse the tree and count the number of nodes. The time complexity is O(n). It gets the Time Limit Exceeded. 

A Better Solution:
A better idea is to get the height of the left-most part, and height of the right-most part. If the left height and right height are the same, means the tree is full. Then the number of nodes is 2^h - 1. If not, we recursively count the number of nodes for the left sub-tree and right sub-tree. 

Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public int countNodes(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int leftHeight = findLeftHeight(root);
        int rightHeight = findRightHeight(root);
        
        if (leftHeight == rightHeight) {
            return (2 << (leftHeight - 1)) - 1;
        }
        
        return countNodes(root.left) + countNodes(root.right) + 1;
    }
    
    private int findLeftHeight(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int height = 1;
        
        while (root.left != null) {
            height++;
            root = root.left;
        }
        
        return height;
    }
    
    private int findRightHeight(TreeNode root) {
        if (root == null) {
            return 0;
        }
        
        int height = 1;
        
        while (root.right != null) {
            height++;
            root = root.right;
        }
        
        return height;
    }
}

The time complexity is O(h^2), because calculating the height of a binary tree takes O(h) time, and it recursively traverse the tree by O(h) time. 
In more detail, in worst case, we need to calculate the height of the tree in 1 + 2 + 3 + 4 + ... + h = O(h^2) time. It is actually 2 * O(h^2) because we need to calculate the left and right height. 

Friday, August 28, 2015

Leetcode: Binary Tree Right Side View

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.
For example:
Given the following binary tree,
   1            <---
 /   \
2     3         <---
 \     \
  5     4       <---
You should return [1, 3, 4].
Idea:
Obviously, the question asks for a BFS. The major difference from the traditional BFS is it only prints the right-most nodes for each level. Consequently, the basic idea is to add right child before adding the left child. For each level, only print out the first node, which must be the right-most node. 

Code (Java):
/**
 * Definition for binary tree
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        if (root == null) {
            return result;
        }
        
        Queue<TreeNode> queue = new LinkedList<TreeNode>();
        queue.offer(root);
        
        while (!queue.isEmpty()) {
            int size = queue.size();
            for (int i = 0; i < size; i++) {
                TreeNode curr = queue.poll();
                if (i == 0) {
                    result.add(curr.val);
                }
                if (curr.right != null) {
                    queue.offer(curr.right);
                }
                
                if (curr.left != null) {
                    queue.offer(curr.left);
                }
            }
        }
        
        return result;
    }
}

A DFS solution: 
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<Integer>();
        
        if (root == null) {
            return result;
        }
        
        rightSideViewHelper(root, 0, result);
        
        return result;
    }
    
    private void rightSideViewHelper(TreeNode root, int level, List<Integer> result) {
        if (root == null) {
            return;
        }
        
        if (level == result.size()) {
            result.add(root.val);
        }
        
        rightSideViewHelper(root.right, level + 1, result);
        rightSideViewHelper(root.left, level + 1, result);
    }
}

Tuesday, August 25, 2015

Leetcode: Lowest Common Ancestor of a Binary Tree

http://buttercola.blogspot.com/2014/11/facebook-lca-without-parent-pointer.html

Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself).”
        _______3______
       /              \
    ___5__          ___1__
   /      \        /      \
   6      _2       0       8
         /  \
         7   4
For example, the lowest common ancestor (LCA) of nodes 5 and 1 is 3. Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.
Code (Java):
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    private TreeNode[] level = new TreeNode[100000];
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || p == null || q == null) {
            return null;
        }
        
        List<TreeNode> path1 = new ArrayList<TreeNode>();
        List<TreeNode> path2 = new ArrayList<TreeNode>();
        
        if (!verticalTraverse(root, p, path1, 0)) {
            return null;
        }
        
        if (!verticalTraverse(root, q, path2, 0)) {
            return null;
        }
        
        TreeNode result = null;
        int i = 0;
        int j = 0;
        while (i < path1.size() && j < path2.size()) {
            if (path1.get(i) != path2.get(j)) {
                return path1.get(i - 1);
            }
            i++;
            j++;
        }
        
        return path1.get(i - 1);
    }
    
    private boolean verticalTraverse(TreeNode root, TreeNode p, List<TreeNode> path, int i) {
        if (root == null) {
            return false;
        }
        
        level[i] = root;
        
        if (root == p) {
            for (int j = 0; j <= i; j++) {
                path.add(level[j]);
            }
            return true;
        }
        
        if (root.left != null && verticalTraverse(root.left, p, path, i + 1)) {
            return true;
        }
        
        if (root.right != null && verticalTraverse(root.right, p, path, i + 1)) {
            return true;
        }
        
        return false;
    }
}



A neat Divide-and-Conquer solution:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || root == p || root == q) {
            return root;
        }
        
        // Divide
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        
        if (left != null && right != null) {
            return root;
        }
        
        if (left != null) {
            return left;
        }
        
        if (right != null) {
            return right;
        }
        
        return null;
    }
}

Update on 11/5/15:
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
public class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if (root == null || p == null || q == null) {
            return null;
        }
        
        List<TreeNode> list1 = new ArrayList<>();
        List<TreeNode> list2 = new ArrayList<>();
        
        if (!getPath(root, p, list1)) {
            return null;
        }
        
        if (!getPath(root, q, list2)) {
            return null;
        }
        
        int i = 0;
        for (i = 0; i < list1.size() && i < list2.size(); i++) {
            if (list1.get(i) != list2.get(i)) {
                return list1.get(i - 1);
            }
        }
        
        return list1.get(i - 1);
    }
    
    private boolean getPath(TreeNode root, TreeNode target, List<TreeNode> result) {
        if (root == null) {
            return false;
        }
        
        result.add(root);
        
        if (root == target) {
            return true;
        }
        
        if (root.left != null) {
            if (getPath(root.left, target, result)) {
                return true; 
            } else {
                result.remove(result.size() - 1);
            }
        }
        
        if (root.right != null) {
            if (getPath(root.right, target, result)) {
                return true;
            } else {
                result.remove(result.size() - 1);
            }
        }
        
        return false;
    }
}

Follow-up:
What if there is a pointer to the parent?
Method 1: traditional method by using extra space
public class Solution {
    private ArrayList<TreeNode> getPath2Root(TreeNode node) {
        ArrayList<TreeNode> list = new ArrayList<TreeNode>();
        while (node != null) {
            list.add(node);
            node = node.parent;
        }
        return list;
    }
    public TreeNode lowestCommonAncestor(TreeNode node1, TreeNode node2) {
        ArrayList<TreeNode> list1 = getPath2Root(node1);
        ArrayList<TreeNode> list2 = getPath2Root(node2);
        
        int i, j;
        for (i = list1.size() - 1, j = list2.size() - 1; 
          i >= 0 && j >= 0; i--, j--) {
            if (list1.get(i) != list2.get(j)) {
                return list1.get(i).parent;
            }
        }
        return list1.get(i+1);
    }
}

Method 2: without using extra space
public Node findLCA(Node root, Node p, Node q) {
   if (root == null || p == null || q == null) return null;
   int depth1 = getDepth(root, p);
   int depth2 = getDepth(root, q);
   if (depth1 > depth2) {
      swap(depth1, depth2);
      swap(p, q);
   }
   for (int i = 0; i < depth1 - depth2; i++) {
      q = q.parent;
   }
   while (p) {
      if (p == q) return p;
      p = p.parent;
      q = q.parent;
   }
   return null;
}

public int getDepth(Node root, Node n) {
   if (root == null || n == null) return null;
   int depth = 0;
   while (root != n) {
      depth++;
      n = n.parent;
   }
   return depth;
}

public void swap(Object<T> a, Object<T> b) {
   Object<T> tmp = a;
   a = b;
   b = tmp;
}