本题考查
二叉树,最深公共祖先LCA
思路
- 版本一思路:每次模拟建树过程找到该迭代对应的先序遍历数组与中序遍历数组
- 版本二思路:比版本一省去了数组,直接用数组元素下标表示该迭代对应的遍历数组,并且使用map存储对应元素在中序遍历当中的位置,便于确定查找的两结点相对于现阶段根结点的位置。
若a和b在根结点的左边,则a和b的最近公共祖先在当前子树根结点的左子树寻找,如果a和b在当前子树根结点的两边,在当前子树的根结点就是a和b的最近公共祖先,如果a和b在当前子树根结点的右边,则a和b的最近公共祖先就在当前子树的右子树寻找。
版本二代码参考:柳神博客
代码
版本一后两个用例超限
版本二倒数第二个用例错误,但柳神源代码是AC的,不知道为啥改写成JAVA之后会出现错误
版本一:
import java.util.Arrays;
import java.util.Scanner;
public class Main {
static boolean isExit(int i, int[] arr) {
for(int j : arr)
if(j == i) return true;
return false;
}
static void find(int[] preOrder, int[] inOrder, int temp1, int temp2) {
int index = -1;
for(int i = 0 ; i < inOrder.length ; i++)
if(inOrder[i] == preOrder[0]) {index = i; break;}
int[] leftPre = Arrays.copyOfRange(preOrder, 1, 1+index);
int[] leftIn = Arrays.copyOfRange(inOrder, 0, index);
int[] rightPre = Arrays.copyOfRange(preOrder, 1+index, preOrder.length);
int[] rightIn = Arrays.copyOfRange(inOrder, index+1, inOrder.length);
if (leftPre.length > 0 && isExit(temp1, leftPre) && isExit(temp2, leftPre))
find(leftPre, leftIn, temp1, temp2);
else if (rightPre.length > 0 && isExit(temp1, rightPre) && isExit(temp2, rightPre))
find(rightPre, rightIn, temp1, temp2);
else if (preOrder[0] != temp1 && preOrder[0] != temp2)
System.out.println("LCA of " + temp1 + " and " + temp2 + " is " + preOrder[0] + ".");
else if (preOrder[0] == temp1)
System.out.println(temp1 + " is an ancestor of " + temp2 + ".");
else
System.out.println(temp2 + " is an ancestor of " + temp1 + ".");
}
public static void main(String[] args) {
Scanner scaner = new Scanner(System.in);
int round = scaner.nextInt();
int nodeNum = scaner.nextInt();
int[] inOrder = new int[nodeNum];int[] preOrder = new int[nodeNum];
for (int i = 0; i < nodeNum; i++) inOrder[i] = scaner.nextInt();
for (int i = 0; i < nodeNum; i++) preOrder[i] = scaner.nextInt();
for (int i = 0; i < round; i++) {
int temp1 = scaner.nextInt();
int temp2 = scaner.nextInt();
if(!isExit(temp1, preOrder) && !isExit(temp2, preOrder))
System.out.println("ERROR: " + temp1 + " and " + temp2 + " are not found.");
else if(!isExit(temp1, preOrder))
System.out.println("ERROR: " + temp1 + " is not found.");
else if(!isExit(temp2, preOrder))
System.out.println("ERROR: " + temp2 + " is not found.");
else
find(preOrder, inOrder, temp1, temp2);
}
scaner.close();
}
}
版本二:
import java.util.HashMap;
import java.util.Scanner;
public class Main {
static int[] in, pre;
static HashMap<Integer, Integer> pos;
static void lca(int inl, int inr, int preRoot, int a, int b) {
if (inl > inr) return;
int inRoot = pos.get(pre[preRoot]), aIn = pos.get(a), bIn = pos.get(b);
if (aIn < inRoot && bIn < inRoot) lca(inl, inRoot-1, preRoot+1, a, b);
else if (aIn > inRoot && bIn > inRoot) lca(inRoot+1, inr, preRoot+1+(inRoot-inl), a, b);
else if (aIn == inRoot) System.out.println(a+" is an ancestor of "+b+".");
else if (bIn == inRoot) System.out.println(b+" is an ancestor of "+a+".");
else System.out.println("LCA of "+a+" and "+b+" is "+in[inRoot]+".");
}
public static void main(String[] args) {
Scanner scaner = new Scanner(System.in);
pos = new HashMap<Integer, Integer>();
int m, n, a, b;
m = scaner.nextInt(); n = scaner.nextInt();
in = new int[n+1];
pre = new int[n+1];
for (int i = 1; i <= n; i++) {
in[i] = scaner.nextInt();
pos.put(in[i], i);
}
for (int i = 1; i <= n; i++) pre[i] = scaner.nextInt();
for (int i = 0; i < m; i++) {
a = scaner.nextInt();
b = scaner.nextInt();
if (pos.get(a) == null && pos.get(b) == null)
System.out.println("ERROR: "+a+" and "+b+" are not found.");
else if (pos.get(a) == null)
System.out.println("ERROR: "+a+" is not found.");
else if (pos.get(b) == null)
System.out.println("ERROR: "+b+" is not found.");
else
lca(1, n, 1, a, b);
}
scaner.close();
}
}