题目1509:树中两个结点的最低公共祖先 剑指的40

本文介绍了一种寻找二叉树中两个指定节点的最低公共祖先的算法,并提供了一个具体的Java实现示例。该算法避免使用额外的数据结构来存储节点,适用于非二叉搜索树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目1509:树中两个结点的最低公共祖先

时间限制:1 秒

内存限制:128 兆

特殊判题:

提交:203

解决:57

题目描述:

给定一棵树,同时给出树中的两个结点,求它们的最低公共祖先。

输入:

输入可能包含多个测试样例。
对于每个测试案例,输入的第一行为一个数n(0<n<1000),代表测试样例的个数。
其中每个测试样例包括两行,第一行为一个二叉树的先序遍历序列,其中左右子树若为空则用0代替,其中二叉树的结点个数node_num<10000。
第二行为树中的两个结点的值m1与m2(0<m1,m2<10000)。

输出:

对应每个测试案例,
输出给定的树中两个结点的最低公共祖先结点的值,若两个给定结点无最低公共祖先,则输出“My God”。

样例输入:
2
1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
6 8
1 2 4 6 0 0 7 0 0 5 8 0 0 9 0 0 3 0 0
6 12
样例输出:
2
My God
 
     
package Tree;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Scanner;

/**
 * @Title: Tree_findCommonAncestor.java
 * @Package Tree
 * @Description: Design an algorithm and write code to find the first common
 *               ancestor of two nodes in a binary tree Avoid storing additional
 *               nodes in a data structure NOTE: This is not necessarily a
 *               binary search tree
 * @author nutc
 * @date 2013-7-23 上午9:27:14
 * @version V1.0
 */
public class Tree_findCommonAncestor2 {

	
	public static void main(String args[]){
		int n;
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();
		sc.nextLine(); //非常重要,读取多出来的回车!
		while(n>0){
			String[] str = sc.nextLine().split(" ");
			int [] num = new int[str.length];
			for(int i=0;i<num.length;i++){
				num[i]=Integer.parseInt(str[i]);
			}
			FatherNode root = buildTree(num);
//			root.display();
			int n1,n2 ;
			n1 = sc.nextInt();
			n2 = sc.nextInt();
			sc.nextLine();  //非常重要,读取多出来的回车!
			FatherNode com = findCom(root,n1,n2);
			if(com!=null)
				System.out.println(String.valueOf(com.value));
			else{
				System.out.println("My God");
			}
			n--;
		}
	}
	
	public static FatherNode buildTree(int[] num){
		if(num==null) return null;
		FatherNode root = new FatherNode(num[0]);
		FatherNode now = root;
		int index=1;
		while(index<num.length){
//			System.out.println(now.value);
			if(num[index]!=0){
				if(now.left==null){   //全部写反了。。。写成了 !=
					now.left = new FatherNode(num[index]);
					now.left.father = now;  //父亲和儿子 不是可逆的!!!
					now = now.left;
					index ++;
				}else if(now.right==null){
					now.right = new FatherNode(num[index]);
					now.right.father = now;   //父亲和儿子 不是可逆的!!!
					now = now.right;
					index++;
				}else{
					now = now.father;
				}
			}else{
				now = now.father;
				index+=2;
			}
		}
		return root;
	}
	
	public static FatherNode findCom(FatherNode root,int n1,int n2){
		if(root==null) return null;
		LinkedList<FatherNode> list1 = new LinkedList<FatherNode>();
		LinkedList<FatherNode> list2 = new LinkedList<FatherNode>();
		findList(root,n1,list1);
		findList(root,n2,list2);
//		System.out.println(list1.toString());
		Iterator<FatherNode> it1 = list1.iterator();  //要限定类型啊亲!!!啊亲!!!
		Iterator<FatherNode> it2 = list2.iterator();
		FatherNode last = null;
		while(it1.hasNext() && it2.hasNext()){
			FatherNode f1 = it1.next();  //不是   it2 = it2.next();
			FatherNode f2 = it2.next();  //必须把node取出来比较,不能直接比较 it1 和 it2!!!
//			System.out.println(f1+" -- "+f2);
			if(f1 == f2){
				last = f1;
			}else{
				break;
			}
		}
		return last;
	}
	
	public static boolean findList(FatherNode root,int n,LinkedList<FatherNode> list){
		if(root ==null) return false;
		list.add(root);
		if(root.value == n){
			return true;
		}
		boolean iffound = false;
		iffound = findList(root.left,n,list);
		if(!iffound)
			iffound = findList(root.right,n,list);
		
		if(!iffound)  list.removeLast();  //remove 默认山第一个
		return iffound;
	}
	
	
	public static class FatherNode {
		FatherNode left;
		FatherNode right;
		FatherNode father;
		int value;

		public FatherNode(int v) {
			value = v;
			father = null;
			left = right = null;
		}

		public void display() {
			System.out.print("当前" + value);
			if (left != null) {
				System.out.print("  左边" + left.value);
			}
			if (right != null) {
				System.out.print("   右边" + right.value);
			}
			System.out.println();
			if (left != null)
				left.display();
			if (right != null)
				right.display();

		}
		
		public void addLeft(FatherNode n){
			left = n;
			n.father = this;
		}
		
		public void addRight(FatherNode n){
			right = n;
			n.father = this;
		}
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值