1. 程式人生 > 實用技巧 >PAT甲級1143Lowest Common Ancestor

PAT甲級1143Lowest Common Ancestor

題目連結

https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312

題解

題目要求

  • 最近公共祖先(LCA,The lowest common ancestor)

    在一顆樹中,結點U和V的LCA是U和V為其後代的深度最大的結點。

  • 二叉搜尋樹(BST,binary search tree)

    • 樹中的每個結點的值都大於其左子樹中結點的值
    • 樹中的每個結點的值都不超過其右子樹中結點的值
    • 每個結點的左子樹和右子樹都是二叉搜尋樹

給定一個二叉搜尋樹中的任意兩個結點,請找到他們的LCA。

  • 輸入

    • M:正整數,不超過1000,需要測試的結點對的數量
    • N:正整數,不超過10000,二叉搜尋樹中結點的數量
    • N個結點(互異):按照先序遍歷的順序給出,值都在int範圍內
    • M個結點對
  • 輸出

    對於每個結點對,判斷結點對中每個結點是否存在,如果都存在則找到他們的LCA。

解題思路

不需建樹

  • 判斷結點是否在樹中

    讀取樹的先序遍歷時使用map記錄一個結點是否在樹中

  • 尋找LCA

    根據BST的性質,如果一個結點的值處於u和v的值之間,那這個結點就是u和v的LCA。

這道題涉及LCA,也可以看看另外一道題:PAT甲級1151 LCA in a Binary Tree

程式碼

// Problem: PAT Advanced 1143
// URL: https://pintia.cn/problem-sets/994805342720868352/problems/994805343727501312
// Tags: Tree BST LCA map

#include <iostream>
#include <vector>
#include <map>
using namespace std;

int main()
{
    int m, n, u, v, a;
    scanf("%d %d", &m, &n);

    vector<int> preOrder(n);
    map<int, bool> exists;
    for (int i = 0; i < n; i++){ // 讀取先序遍歷結果並記錄結點是否出現過
        scanf("%d", &preOrder[i]);
        exists[preOrder[i]] = true;
    }

    while (m--) { // m個結點對
        scanf("%d %d", &u, &v);

        for (int i = 0; i < n; i++){ // 尋找LCA
            a = preOrder[i];
            if (u < a && v > a || v < a && u > a || (a == u) || (a == v) )
                break;
        }

        if (exists[u] == false && exists[v] == false)
            printf("ERROR: %d and %d are not found.\n", u, v);
        else if (exists[u] == false || exists[v] == false)
            printf("ERROR: %d is not found.\n", exists[u]==false ? u : v);
        else if (a == u || a == v)
            printf("%d is an ancestor of %d.\n", a, a == u ?  v : u);
        else
            printf("LCA of %d and %d is %d.\n", u, v, a);
    }

    return 0;
}

作者:@臭鹹魚

轉載請註明出處:https://www.cnblogs.com/chouxianyu/

歡迎討論和交流!