import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 * }
 */

public class Solution {
    /**
     * 
     * @param root TreeNode类 
     * @param o1 int整型 
     * @param o2 int整型 
     * @return int整型
     */
    public int lowestCommonAncestor (TreeNode root, int o1, int o2) {
        // write code here
        //第一步 层序遍历 放入list中 顺便找出这两个节点以及所在的层数
        List<List<TreeNode>> list = new ArrayList<>();
        TreeNode node1 = null;
        TreeNode node2 = null;
        //这两个节点可能不在一层
        int lineNum1 = -1;
        int lineNum2 = -1;
        boolean isFindNode1 = false;
        boolean isFindNode2 = false;
        Queue<TreeNode> q = new LinkedList<>();
        q.offer(root);
        while(!q.isEmpty()){
            if(!isFindNode1){
                lineNum1 += 1;
            }
            if(!isFindNode2){
                lineNum2 += 1;
            }
            int size = q.size();
            List<TreeNode> line = new ArrayList<>();
            for(int i = 0;i<size;i++){
                TreeNode next = q.poll();
                line.add(next);
                if(next.val == o1){
                    node1 = next;
                    isFindNode1 = true;
                }
                if(next.val == o2){
                    node2 = next;
                    isFindNode2 = true;
                }
                if(isFindNode1 && isFindNode2){
                     break;
                }
                if(next.left != null){
                    q.offer(next.left);
                }
                if(next.right != null){
                    q.offer(next.right);
                }
            }
            list.add(line);
        }
        //第二步 从上一层中找他们的父亲  判断是否相等
        if(lineNum2 != lineNum1){
            //不是同一层 先找到同一层的值
            if(lineNum2 > lineNum1){
                node2 = findNode(lineNum1,lineNum2,list,node2);
            } else {
                node1 = findNode(lineNum2,lineNum1,list,node1);
            }
        }
        if(node1 == node2){
            return node1.val;
        }
        int val = findParent(lineNum1,node1,node2,list);
        return val;
        //第三步 重复第二步
    }

    public TreeNode findNode(int smallNum,int bigNum,List<List<TreeNode>> list,TreeNode node){
        TreeNode p = node;
        while(bigNum >= smallNum){
            List<TreeNode> l = list.get(bigNum);
            for(int i =0;i<l.size();i++){
                TreeNode next = l.get(i);
                if(next.left == p || next.right == p){
                    p = next;
                    break;
                }
            }
            bigNum --;
        }
        return p;
    }

    public int findParent(int line,TreeNode node1,TreeNode node2, List<List<TreeNode>> list){
        //从上一层中找到他们的父亲并对比
        TreeNode p1 = null;
        TreeNode p2 = null;
        List<TreeNode> l = list.get(line - 1);
        for(int i =0;i<l.size();i++){
            TreeNode next = l.get(i);
            if(next.left == node1 || next.right == node1){
                p1 = next;
            }
            if(next.left == node2 || next.right == node2){
                p2 = next;
            }
        }
        if(p1 == p2){
            return p1.val;
        } else {
            int nextLine = line -1;
            return findParent(nextLine,p1,p2,list);
        }
    }
}