PAT甲级1151 LCA in a Binary Tree(JAVA版)

31 篇文章 0 订阅

本题考查

二叉树,最深公共祖先LCA

思路

  1. 版本一思路:每次模拟建树过程找到该迭代对应的先序遍历数组与中序遍历数组
  2. 版本二思路:比版本一省去了数组,直接用数组元素下标表示该迭代对应的遍历数组,并且使用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();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值