二叉树
题目描述
1
/ \
2 3
/ \ / \
4 5 6 7
/ \ / \ / \ / \
如上图所示,由正整数 1, 2, 3, …组成了一棵无限大的二叉树。
从某一个结点到根结点(编号是1的结点)都有一条唯一的路径,比如从5到根结点的路径是(5, 2, 1),从4到根结点的路径是(4, 2, 1),从根结点1到根结点的路径上只包含一个结点1,因此路径就是(1)。
对于两个结点x和y,假设他们到根结点的路径分别是(x1, x2, … ,1)和(y1, y2,…,1),那么必然存在两个正整数i和j,使得从xi 和yj 开始,有xi = yj,xi + 1 = yj + 1,xi + 2 = yj + 2,…
现在的问题就是,给定x和y,要求他们的公共父结点,即xi(也就是 yj)。
要求:
输入:输入包含多组数据,每组数据包含两个正整数x和y(1≤x, y≤2^31-1)。
输出:对应每一组数据,输出一个正整数xi,即它们的首个公共父结点。
示例:
输入:10 4
输出:2
题目分析
其实这个题很简单,考察的是二叉树的性质。
二叉树从1到n按编码排序,则对于编号为i的结点来说,其左子树为2i,右子树为2i+1。
也就是说,对于编号为i的结点来说,其父结点的编号为i/2。
进而,解题思路如下:
对于输入的两个结点编号x,y:
- 如果x=y,那么其首个公共结点就是本身;
- 如果x!=y,那么就求编号大的结点的父结点编号,并更新编号,即如果x>y,那么求x的父结点的编号值,并将该值赋给x。
经过这样的步骤,x和y不断更新为其父结点的编号,那么第一次x=y的编号就是x和y的首个公共父结点。
代码实现
#include<stdio.h>
int main(){
int x,y;
while(scanf("%d %d",&x,&y) != EOF){
while(x!=y){
x>y ? (x/=2) : (y/=2);
}
printf("%d\n",x);
}
return 0;
}