题目描述

The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U and V as descendants.Given any two nodes in a binary tree, you are supposed to find their LCA.


最小共同祖先(LCA)是一棵树中两个节点U和V最深的那个公共父节点。要求给一棵树,以及两个节点,请你找出它们的LCA。

输入说明

Each input file contains one test case. For each case, the first line gives two positive integers: M (≤ 1,000), the number of pairs of nodes to be tested; and N (≤ 10,000), the number of keys in the binary tree, respectively. In each of the following two lines, N distinct integers are given as the inorder and preorder traversal sequences of the binary tree, respectively. It is guaranteed that the binary tree can be uniquely determined by the input sequences. Then M lines follow, each contains a pair of integer keys U and V. All the keys are in the range of int.


每个输入包含一个测试用例。

在每个测试用例中,第一行给定两个正整数M和N。M(≤ 1,000)是要查询的节点对数,N (≤ 10,000)是这个二叉树的节点总数。

在这之后的两行分别给定为树的中序遍历先序遍历。可以保证的是通过这两个序列可以唯一确定一棵二叉树。

接下来的M行为需要查询LCA的M对节点。

树中节点的值皆为整数。

输出说明

For each given pair of U and V, print in a line LCA of U and V is A. If the LCA is found and A is the key. But if A is one of U and V, print X is an ancestor of Y. where X is A and Y is the other node. If U or V is not found in the binary tree, print in a line ERROR: U is not found. or ERROR: V is not found. or ERROR: U and V are not found..


对于给出的一对节点U和V,如果能找到它们的LCA是A,输出:LCA of U and V is A;如果A是U和V之间的某一个,输出:X is an ancestor of Y,其中XA,而Y代表另外一个节点;

如果U和V没有出现在树中,视情况而定输出:

  • ERROR: U is not found.
  • ERROR: V is not found.
  • ERROR: U and V are not found.

输入示例

6 8
7 2 3 4 6 5 1 8
5 3 7 2 6 4 8 1
2 6
8 1
7 9
12 -3
0 8
99 99

输出示例

LCA of 2 and 6 is 3.
8 is an ancestor of 1.
ERROR: 9 is not found.
ERROR: 12 and -3 are not found.
ERROR: 0 is not found.
ERROR: 99 and 99 are not found.

算法

我记得第一次考PAT看到这题时,我很愚蠢地用了以下算法:

  1. 通过中序遍历和先序遍历先建了一棵树;
  2. 声明两个向量Upath和Vpath分别存放两个路径。然后在树中找到U和V的位置,并将路径上的节点依次存入向量;
  3. 从前往后同时遍历两个向量,理论上来说,第一个分叉点是U和V的LCA,当然还夹杂着其中一个节点是否为另一节点的祖先这样的判断。

当然在机考上这题我没有写完,只悲催地得了9分,印象深刻。

后来过了半年,第二次准备考PAT的前一个月时,我刷到这题,还是复制着当时的想法,这次写出来了,29分。我不知道最后1分扣在哪里,很难想出来。写出代码用时40分钟吧,因为在场下,心平气和的。之后考完18年冬季的PAT后再刷Leet-Code的时候遇到这一题,这次不知咋的,可能是刷的题目多了,我没有这么愚蠢了。下面先贴出那个29分的“愚蠢”版

“愚蠢”版

#include <iostream>
#include <vector>
#include <deque>
using namespace std; typedef struct node
{
int var;
struct node *left, *right, *father;
}tree; int M, N, FindFlag;
tree *T;
vector<int> inorder, preorder;
tree* createTree(tree*, int, int, int, int);
void findLCA(int U, int V);
void findX(int x, tree *p, tree *&Node); int main() {
//freopen("/Users/shayue/Desktop/stdin.txt", "r", stdin);
cin >> M >> N; int tmp;
for(int i = 0; i< N; i++)
{
cin >> tmp;
inorder.push_back(tmp);
} for(int i = 0; i< N; i++)
{
cin >> tmp;
preorder.push_back(tmp);
} int leftOfIn, rightOfIn, leftOfPre, rightOfPre;
leftOfIn = leftOfPre = 0;
rightOfIn = rightOfPre = N - 1;
T = createTree(T, leftOfIn, rightOfIn, leftOfPre, rightOfPre);
T->father = NULL; int U, V;
int UNotFound, VNotFound;
for(int i = 0; i < M; i++)
{
cin >> U >> V;
UNotFound = VNotFound = 0; //标记为0时表明该数不在数组中
// 下面代码先判断U和V节点是不是在这颗树中
for(int i = 0; i < preorder.size(); i++)
{
if(preorder[i] == U)
UNotFound = 1;
if(preorder[i] == V)
VNotFound = 1;
} if(UNotFound == 0 && VNotFound == 0)
printf("ERROR: %d and %d are not found.\n", U, V);
else if(UNotFound == 0)
printf("ERROR: %d is not found.\n", U);
else if(VNotFound == 0)
printf("ERROR: %d is not found.\n", V);
else
// 两个节点都在树中时,进入函数
findLCA(U, V);
}
return 0;
} tree* createTree(tree* T, int leftOfIn, int rightOfIn, int leftOfPre, int rightOfPre)
{
int root = preorder[leftOfPre];
if(leftOfIn < rightOfIn && leftOfPre < rightOfPre)
{
int root = preorder[leftOfPre], i;
T = new tree();
T->var = root;
T->left = T->right = NULL;
leftOfPre = leftOfPre + 1;
//找到root在中序序列中的下标
for(i = leftOfIn; i < N && inorder[i] != root; i++);
int differ = i - leftOfIn;
T->left = createTree(T->left, leftOfIn, i-1, leftOfPre, leftOfPre+differ-1);
if(T->left != NULL)
T->left->father = T;
T->right = createTree(T->right, i+1, rightOfIn, leftOfPre+differ, rightOfPre);
if(T->right != NULL)
T->right->father = T;
}else if(leftOfIn == rightOfIn && leftOfPre == rightOfPre)
{
T = new tree();
T->var = root;
T->left = T->right = NULL;
}
return T;
} void findLCA(int U, int V){
deque<int> UPath, VPath;
tree *UNode, *VNode;
FindFlag = 0;
findX(U, T, UNode);
FindFlag = 0;
findX(V, T, VNode);
// UNode和VNode指向U和V节点在树中的位置,根据father指针找到父节点
while(UNode != NULL)
{
UPath.push_front(UNode->var);
UNode = UNode->father;
}
while(VNode != NULL)
{
VPath.push_front(VNode->var);
VNode = VNode->father;
}
int Usize = UPath.size();
int Vsize = VPath.size();
if(U == V)
{
printf("LCA of %d and %d is %d.\n", U, V, UPath[Usize-2]);
return;
} int i, j, flag = 0;
for(i = 0, j = 0; i < Usize && j < Vsize; i++, j++)
{
if(UPath[i] != VPath[j])
{
flag = 1;
break;
}
} if(flag == 0) //自然而然地走完
{
if(i == Usize)
printf("%d is an ancestor of %d.\n", U, V);
if(j == Vsize)
printf("%d is an ancestor of %d.\n", V, U);
}else
printf("LCA of %d and %d is %d.\n", U, V, UPath[i-1]);
} void findX(int x, tree *p, tree *&Node)
{
if(p)
{
if(x == p->var){
Node = p;
FindFlag = 1;
return;
}
else
{
findX(x, p->left, Node);
if(FindFlag == 1)
return;
findX(x, p->right, Node);
if(FindFlag == 1)
return;
}
}
}

让我再看一遍这个代码是痛苦的,我都不知道我居然能想出这么多参数来

【PAT 甲级】1151 LCA in a Binary Tree (30 分)的更多相关文章

  1. PAT 甲级 1151 LCA in a Binary Tree

    https://pintia.cn/problem-sets/994805342720868352/problems/1038430130011897856 The lowest common anc ...

  2. PAT甲级|1151 LCA in a Binary Tree 先序中序遍历建树 lca

    给定先序中序遍历的序列,可以确定一颗唯一的树 先序遍历第一个遍历到的是根,中序遍历确定左右子树 查结点a和结点b的最近公共祖先,简单lca思路: 1.如果a和b分别在当前根的左右子树,当前的根就是最近 ...

  3. PAT Advanced 1151 LCA in a Binary Tree (30) [树的遍历,LCA算法]

    题目 The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both ...

  4. 【PAT甲级】1102 Invert a Binary Tree (25 分)(层次遍历和中序遍历)

    题意: 输入一个正整数N(<=10),接着输入0~N-1每个结点的左右儿子结点,输出这颗二叉树的反转的层次遍历和中序遍历. AAAAAccepted code: #define HAVE_STR ...

  5. PAT 1151 LCA in a Binary Tree[难][二叉树]

    1151 LCA in a Binary Tree (30 分) The lowest common ancestor (LCA) of two nodes U and V in a tree is ...

  6. PAT甲级:1066 Root of AVL Tree (25分)

    PAT甲级:1066 Root of AVL Tree (25分) 题干 An AVL tree is a self-balancing binary search tree. In an AVL t ...

  7. 1151 LCA in a Binary Tree(30 分)

    The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...

  8. 1151 LCA in a Binary Tree

    The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...

  9. 1151 LCA in a Binary Tree (30point(s))

    The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U ...

随机推荐

  1. JBoss 系列四十九:JBoss 7/WildFly 中端口使用列表

    JBoss 7中端口使用列表 JBoss 7中所有配置都在一个文件中(standaone*.xml, domain.xml),和之前的JBoss相比JBoss 7用到的端口变少,我们将以表格的形式列出 ...

  2. Python自动化开发 - Python操作MySQL

    本篇对于Python操作MySQL主要使用两种方式: 原生模块 pymsql ORM框架 SQLAchemy 一.pymysql pymsql是Python中操作MySQL的模块,其使用方法和mysq ...

  3. DELPHI微信支付代码

    DELPHI微信支付代码   不管是微信支付还是支付宝支付, 3个最棘手的问题是:1,如何生成签名2,支付请求如何提交3, 如何验证签名 下面就围绕这二个问题来讲. 我使用的是XE3. 先看微信支付: ...

  4. Android-AndroidStudio-AVD启动不了-emulator: Process finished with exit code 1

    注意:解决此错误目前只针对Windows系统的电脑: 1.AndroidStudio-->AVDManager(Create Virtual Device): 2.提示AVD启动不了,同时Eve ...

  5. CentOS 7.2通过yum安装MairaDB 10.1

    CentOS 7.2自带的yum源中mysql已经被替换成了mariadb,然而却是5.5版本,匹配mysql5.5,想要使用mysql 5.7的特性需要mariadb 10.0或10.1版本,10. ...

  6. 在EF中使用Expression自动生成p=>new Entity(){X="",Y="",..}格式的Lambda表达式灵活实现按需更新

    一.基本介绍      回忆:最早接触Expression是在学校接触到EF的时候,发现where方法里的参数是Expression<Func<T,bool>>这么一个类型,当 ...

  7. c# WebApi创建及客户端调用

    前段时间学习WebApi的创建与调用,网上的信息千奇百怪(知识有限,看不懂啊),通过查阅资料及借鉴博友实例分析后总结一下,总结一套简单完整的WebApi创建及实例 首先创建一个WebApi服务(流程就 ...

  8. word2vec的原理(一)

    最近上了公司的新员工基础培训课,又对NLP重新产生的兴趣.NLP的第一步大家知道的就是不停的写正则,那个以前学的还可以就不看了.接着就是我们在把NLP的词料在传入神经网络之前的一个预处理,最经典的就是 ...

  9. fatal: LF would be replaced by CRLF in index.html

    进入项目目录,在.git文件夹下打开config配置文件,添加上下面两句话: autocrlf = false safecrlf = false 即可

  10. 创建python3虚拟环境指令和冻结所安装的包

    mkvirtualenv file_name -p python3 去掉后面的 P 和python3 代表创建python2环境 其中p代表路径的意思 冻结所安装包命令 pip freeze > ...