【PAT甲级 - C++题解】1151 LCA in a Binary Tree

简介: 【PAT甲级 - C++题解】1151 LCA in a Binary Tree

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 and V as descendants.


Given any two nodes in a binary tree, you are supposed to find their LCA.

Input Specification:


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.

Output Specification:


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..

Sample Input:

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


Sample Output:

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.

题意


树中两个结点 U 和 V 的最低公共祖先(LCA)是指同时具有 U 和 V 作为后代的最深结点。


第一行输入给定 M MM 和 N NN ,表示有 N NN 个结点和 M MM 行询问。


第二行给定该二叉树的中序遍历结果,第三行给定该二叉树前序遍历的结果。


接下来的 M MM 行表示要查询的两个结点,需要我们查找这两个结点是否在树中且有公共结点,如果有则输出对应结果。


思路


这道题的思路和 1143 那题思路一模一样,只是对于输入的处理稍微不同。这里处理的是二叉树而不是二叉搜索树,所以中序数组和后序数组是给定的,但是同样要先对数据进行离散化后再构建二叉树。


代码部分除了对于输入的处理不同外,其它部分和 1143 那题代码完全相同,那道题我进行了超详细的讲解,这里就不重复讲解啦,大家可以移步到那题去看看是如何实现的~


代码

#include<bits/stdc++.h>
using namespace std;
const int N = 10010;
int m, n;
int seq[N], pre[N];
int p[N], depth[N];
unordered_map<int, int> pos;
//构建二叉树
int build(int il, int ir, int pl, int pr, int d)
{
    int root = pre[pl];   //获得根结点
    int k = root;     //由于数据经历过离散化,所以root等于左子树的结点数
    depth[root] = d;  //记录该结点所在深度
    if (il < k)    p[build(il, k - 1, pl + 1, pl + 1 + k - il - 1, d + 1)] = root; //右子树
    if (ir > k)    p[build(k + 1, ir, pl + 1 + k - il - 1 + 1, pr, d + 1)] = root; //左子树
    return root;
}
int main()
{
    cin >> m >> n;
    //输入中序数组,并对数据进行离散化操作
    for (int i = 0; i < n; i++)
    {
        cin >> seq[i];
        pos[seq[i]] = i;  //对每个值进行离散化
    }
    //输入前序数组,并将前序数组中的值全部替换成离散后的值
    for (int i = 0; i < n; i++)
    {
        cin >> pre[i];
        pre[i] = pos[pre[i]];
    }
    build(0, n - 1, 0, n - 1, 0);   //构建二叉树
    //查找最低公共祖先
    while (m--)
    {
        int a, b;
        cin >> a >> b;
        if (pos.count(a) && pos.count(b))    //如果两个结点都在树中
        {
            a = pos[a], b = pos[b];  //先转换成离散化后的数值
            int x = a, y = b;    //备份要查找的两个结点
            while (a != b) //找到两个结点的公共结点为止
                if (depth[a] < depth[b])   b = p[b];
                else    a = p[a];
            //打印对应结果
            if (a != x && b != y)  printf("LCA of %d and %d is %d.\n", seq[x], seq[y], seq[a]);
            else if (a == x)   printf("%d is an ancestor of %d.\n", seq[x], seq[y]);
            else    printf("%d is an ancestor of %d.\n", seq[y], seq[x]);
        }
        else if (!pos.count(a) && !pos.count(b))  //如果两个结点都不在树中
            printf("ERROR: %d and %d are not found.\n", a, b);
        else if (!pos.count(a))  //如果第一个结点不在树中
            printf("ERROR: %d is not found.\n", a);
        else  //如果第二个结点不在树中
            printf("ERROR: %d is not found.\n", b);
    }
    return 0;
}


目录
相关文章
|
9月前
|
JSON 数据格式 C++
C++ JSON库 nlohmann::basic_json::binary 的用法
C++ JSON库 nlohmann::basic_json::binary 的用法
134 0
|
C++
【PAT甲级 - C++题解】1040 Longest Symmetric String
【PAT甲级 - C++题解】1040 Longest Symmetric String
76 0
|
算法 C++
【PAT甲级 - C++题解】1044 Shopping in Mars
【PAT甲级 - C++题解】1044 Shopping in Mars
107 0
|
C++
【PAT甲级 - C++题解】1117 Eddington Number
【PAT甲级 - C++题解】1117 Eddington Number
95 0
|
2天前
|
编译器 C语言 C++
类和对象的简述(c++篇)
类和对象的简述(c++篇)
|
1月前
|
C++ 芯片
【C++面向对象——类与对象】Computer类(头歌实践教学平台习题)【合集】
声明一个简单的Computer类,含有数据成员芯片(cpu)、内存(ram)、光驱(cdrom)等等,以及两个公有成员函数run、stop。只能在类的内部访问。这是一种数据隐藏的机制,用于保护类的数据不被外部随意修改。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。成员可以在派生类(继承该类的子类)中访问。成员,在类的外部不能直接访问。可以在类的外部直接访问。为了完成本关任务,你需要掌握。
68 19
|
1月前
|
存储 编译器 数据安全/隐私保护
【C++面向对象——类与对象】CPU类(头歌实践教学平台习题)【合集】
声明一个CPU类,包含等级(rank)、频率(frequency)、电压(voltage)等属性,以及两个公有成员函数run、stop。根据提示,在右侧编辑器补充代码,平台会对你编写的代码进行测试。​ 相关知识 类的声明和使用。 类的声明和对象的声明。 构造函数和析构函数的执行。 一、类的声明和使用 1.类的声明基础 在C++中,类是创建对象的蓝图。类的声明定义了类的成员,包括数据成员(变量)和成员函数(方法)。一个简单的类声明示例如下: classMyClass{ public: int
50 13
|
1月前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
51 5
|
1月前
|
存储 算法 搜索推荐
【C++面向对象——群体类和群体数据的组织】实现含排序功能的数组类(头歌实践教学平台习题)【合集】
1. **相关排序和查找算法的原理**:介绍直接插入排序、直接选择排序、冒泡排序和顺序查找的基本原理及其实现代码。 2. **C++ 类与成员函数的定义**:讲解如何定义`Array`类,包括类的声明和实现,以及成员函数的定义与调用。 3. **数组作为类的成员变量的处理**:探讨内存管理和正确访问数组元素的方法,确保在类中正确使用动态分配的数组。 4. **函数参数传递与返回值处理**:解释排序和查找函数的参数传递方式及返回值处理,确保函数功能正确实现。 通过掌握这些知识,可以顺利地将排序和查找算法封装到`Array`类中,并进行测试验证。编程要求是在右侧编辑器补充代码以实现三种排序算法
40 5
|
1月前
|
Serverless 编译器 C++
【C++面向对象——类的多态性与虚函数】计算图像面积(头歌实践教学平台习题)【合集】
本任务要求设计一个矩形类、圆形类和图形基类,计算并输出相应图形面积。相关知识点包括纯虚函数和抽象类的使用。 **目录:** - 任务描述 - 相关知识 - 纯虚函数 - 特点 - 使用场景 - 作用 - 注意事项 - 相关概念对比 - 抽象类的使用 - 定义与概念 - 使用场景 - 编程要求 - 测试说明 - 通关代码 - 测试结果 **任务概述:** 1. **图形基类(Shape)**:包含纯虚函数 `void PrintArea()`。 2. **矩形类(Rectangle)**:继承 Shape 类,重写 `Print
48 4