1758:二叉树

1758:二叉树

  • 总时间限制:

    1000ms

  • 内存限制:

    65536kB

  • 描述

    img 如上图所示,由正整数1, 2, 3, ...组成了一棵无限大的二叉树。从某一个结点到根结点(编号是1的结点)都有一条唯一的路径,比如从10到根结点的路径是(10, 5, 2, 1),从4到根结点的路径是(4, 2, 1),从根结点1到根结点的路径上只包含一个结点1,因此路径就是(1)。对于两个结点x和y,假设他们到根结点的路径分别是(x1, x2, ... ,1)和(y1, y2, ... ,1)(这里显然有x = x1,y = y1),那么必然存在两个正整数i和j,使得从xi 和 yj开始,有xi = yj , xi + 1 = yj + 1, xi + 2 = yj + 2,... 现在的问题就是,给定x和y,要求xi(也就是yj)。

  • 输入

    输入只有一行,包括两个正整数x和y,这两个正整数都不大于1000。

  • 输出

    输出只有一个正整数xi。

  • 样例输入

    10 4

  • 样例输出

    2


这个题比较简单,只需要记住二叉树的一条性质:第i个节点的子节点是2i和2i+1.先找那个路径比较短的,把其路径记录下来,然后路径长的一边走路径一边看当前节点在不在记录的路径中,这里为了节约时间可以各走一步,如果短的那个到头了再只走长的那个

package com.jiading.noi;

import java.util.HashSet;
import java.util.Scanner;

/*
 * 1758:二叉树
 * http://noi.openjudge.cn/ch0306/1758/
 * 比较简单
 */
public class Problem20 {
	public static int findParent(int node) {
		if(node==1) {
			return -1;
		}
		if(node%2==1) {
			node--;
		}
		return node/2;
	}
	public static void main(String[] args) {
		Scanner scanner=new Scanner(System.in);
		int left=scanner.nextInt();
		int right=scanner.nextInt();
		HashSet<Integer>patHashSet=new HashSet<>();
		if(left==right) {
			System.out.println(left);
			return;
		}
		//要求左比右大,也就是左面更低
		if(left<right) {
			int temp=left;
			left=right;
			right=temp;
		}
		if(right==1) {
			System.out.println(1);
			return;
		}
		patHashSet.add(right);
		int leftParent=findParent(left);
		int rightParent=findParent(right);
		while(rightParent!=-1) {
			patHashSet.add(rightParent);
			if(patHashSet.contains(leftParent)) {
				System.out.println(leftParent);
				return;
			}
			left=leftParent;
			right=rightParent;
			leftParent=findParent(left);
			rightParent=findParent(right);
		}
		while(leftParent!=-1) {
			if(patHashSet.contains(leftParent)) {
				System.out.println(leftParent);
				return;
			}
			left=leftParent;
			leftParent=findParent(left);
		}
		System.out.println(1);
		return;
	}
}
posted @ 2020-06-27 12:24  别再闹了  阅读(142)  评论(0)    收藏  举报