178 在二叉树中找到两个节点的最近公共祖先(进阶)
Table of Contents

ac

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;

class TreeNode{
    TreeNode left;
    TreeNode right;
    int val;

    public TreeNode(int val) {
        this.val = val;
        left = null;
        right = null;
    }
}

public class Main {
    public static Scanner sc = new Scanner(System.in);

    public static BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

    public static long mod = (long) Math.pow(2, 29);

    public static void main(String[] args) throws Exception {
        String line;
        String[] strArr;
        line = reader.readLine();
        strArr = line.split(" ");
        int n = Integer.valueOf(strArr[0]);
        int rootVal = Integer.valueOf(strArr[1]);
        Map<Integer, TreeNode> mp = new HashMap<>(n);
        for (int i = 0; i < n; i++) {
            line = reader.readLine();
            strArr = line.split(" ");
            int val = Integer.valueOf(strArr[0]);
            int leftVal = Integer.valueOf(strArr[1]);
            int rightVal = Integer.valueOf(strArr[2]);

            if (!mp.containsKey(val)) {
                mp.put(val, new TreeNode(val));
            }
            if (leftVal != 0) {
                if (!mp.containsKey(leftVal)) {
                    mp.put(leftVal, new TreeNode(leftVal));
                }
                mp.get(val).left = mp.get(leftVal);
            }
            if (rightVal != 0) {
                if (!mp.containsKey(rightVal)) {
                    mp.put(rightVal, new TreeNode(rightVal));
                }
                mp.get(val).right = mp.get(rightVal);
            }
        }
        TreeNode root = mp.get(rootVal);
        // 构造每个节点到其父节点的映射
        Map<Integer, Integer> faMap = new HashMap<>(n);
        Queue<TreeNode> que = new LinkedList<>();
        que.offer(root);
        while (!que.isEmpty()){
            TreeNode node = que.poll();
            if(node.left != null){
                faMap.put(node.left.val, node.val);
                que.offer(node.left);
            }
            if(node.right != null){
                faMap.put(node.right.val, node.val);
                que.offer(node.right);
            }
        }

        n = Integer.valueOf(reader.readLine());
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<n;i++) {
            line = reader.readLine();
            strArr = line.split(" ");
            int p = Integer.valueOf(strArr[0]);
            int q = Integer.valueOf(strArr[1]);
            List<Integer> path1 = getPath(faMap, rootVal, p);
            List<Integer> path2 = getPath(faMap, rootVal, q);
            int ancessor = firstSameRev(path1, path2);
            sb.append(ancessor + "\n");
        }
        System.out.print(sb.toString());
    }

    static List<Integer> getPath( Map<Integer, Integer> faMap, int rootVal ,int val){
        List<Integer> path = new ArrayList<>();
        int fa = val;
        while (fa != rootVal){
            path.add(fa);
            fa = faMap.get(fa);
        }
        path.add(rootVal);
        // 逆序
//        int len = path.size();
//        int i = 0;
//        int j = len - 1;
//        while(i < j){
//            int tmp = path.get(i);
//            path.set(i, path.get(j));
//            path.set(j, tmp);
//            i ++;
//            j --;
//        }
        return path;
    }

    static int firstSameRev( List<Integer> l1,  List<Integer> l2){
        int size1 = l1.size();
        int size2 = l2.size();
        int i = size1 - 1;
        int j = size2 - 1;
        while (i >= 0 && j >= 0 && l1.get(i).equals(l2.get(j))){
            i --;
            j --;
        }
        return l1.get(i + 1);
    }

    static int firstSame( List<Integer> l1,  List<Integer> l2){
        int size1 = l1.size();
        int size2 = l2.size();
        int i = 0;
        int j = 0;
        while (i < size1 && j < size2 && l1.get(i).equals(l2.get(j))){
            i ++;
            j ++;
        }
        return l1.get(i - 1);
    }
}
/*
         1
      /     \
     2        3
    / \      / \
   4  5     6  7
              /
             8

8 1
1 2 3
2 4 5
4 0 0
5 0 0
3 6 7
6 0 0
7 8 0
8 0 0
4
4 5
5 2
6 8
5 8

2
2
3
1
 */