卡码网11. 共同祖先

原理

问题目标:根据输入的父子关系,找到小明(编号1)和小宇(编号2)的 ​共同祖先,并比较两人在该祖先下的辈分关系(长辈、晚辈或兄弟)。

核心思路

  1. 假设存在共同根节点:通过遍历所有输入的父节点,记录最大的父节点值 maxnum,假设其为整个族谱的 ​根节点
  2. 计算到根节点的步数:从小明和小宇分别向上遍历父节点,直到到达 maxnum 或父节点不存在,统计步数 counta 和 countb
  3. 比较步数:若 counta > countb,说明小明辈分更高;反之小宇辈分更高;步数相同则为兄弟。

步骤

  1. 输入处理:读取父子关系,用哈希表 map 存储(键为子节点,值为父节点),并记录最大的父节点值 maxnum
  2. 计算小明到根节点的步数:从节点1出发,依次向上遍历父节点,直到父节点为 maxnum 或不存在,统计步数 counta
  3. 计算小宇到根节点的步数:同理从节点2出发,统计步数 countb
  4. 比较步数:根据 counta 和 countb 的大小输出结果。

图示法表示步骤(输入父子关系:[[1,3],[3,5],[2,4],[4,5]]

1. 输入处理:  
   map = {1→3, 3→5, 2→4, 4→5}  
   maxnum = 5(所有父节点中的最大值)  

2. 小明路径:1 → 3 → 5(共2步)  
   小宇路径:2 → 4 → 5(共2步)  

3. 比较步数:counta=2,countb=2 → 输出 "You are my brother"  

代码关键行注释

int main() {  
    int n;  
    while (cin >> n) {  
        int a, b;  
        int counta = 0, countb = 0;  
        int maxnum = 0;  
        unordered_map<int, int> map;  // 存储父子关系(子→父)  
        for (int i = 0; i < n; i++) {  
            cin >> a >> b;  
            map[a] = b;  
            maxnum = max(maxnum, b);  // 记录最大的父节点值(假设为根节点)  
        }  

        // 计算小明到根节点的步数  
        a = 1;  
        while (map[a] && map[a] != maxnum) {  // 遍历父节点,直到到达maxnum或父节点不存在  
            a = map[a];  
            counta++;  
        }  

        // 计算小宇到根节点的步数  
        b = 2;  
        while (map[b] && map[b] != maxnum) {  
            b = map[b];  
            countb++;  
        }  

        // 比较步数输出结果  
        if (counta > countb)  
            cout << "You are my elder" << endl;  
        else if (counta < countb)  
            cout << "You are my younger" << endl;  
        else  
            cout << "You are my brother" << endl;  
    }  
}  

完整代码

#include <iostream>  
#include <unordered_map>  
#include <algorithm>  
using namespace std;  

int main() {  
    int n;  
    while (cin >> n) {  
        int a, b;  
        int counta = 0, countb = 0;  
        int maxnum = 0;  
        unordered_map<int, int> map;  
        for (int i = 0; i < n; i++) {  
            cin >> a >> b;  
            map[a] = b;  
            maxnum = max(maxnum, b);  
        }  
        a = 1;  
        while (map[a] && map[a] != maxnum) {  
            a = map[a];  
            counta++;  
        }  
        b = 2;  
        while (map[b] && map[b] != maxnum) {  
            b = map[b];  
            countb++;  
        }  
        if (counta > countb)  
            cout << "You are my elder" << endl;  
        else if (counta < countb)  
            cout << "You are my younger" << endl;  
        else  
            cout << "You are my brother" << endl;  
    }  
}  

时间复杂度

  • 时间复杂度
    • 输入处理:O(n),遍历 n 对父子关系。
    • 计算步数:最坏 O(h),其中 h 是树的高度。
    • 总体时间复杂度:O(n+h),通常为线性复杂度。
  • 空间复杂度:O(n),存储哈希表 map

总结

  1. 算法正确性
    • 假设输入数据构成单根树:即所有节点最终指向同一个根节点 maxnum。若输入不满足此条件(如存在多个根节点),代码可能错误。
    • 示例验证(如上述父子关系)结果正确。
  2. 代码特点
    • 简化了族谱链的存储,直接通过遍历父节点计算步数。
    • 依赖 maxnum 作为根节点的假设,适用于题目隐含单根树的场景。
  3. 潜在问题
    • 若存在多个根节点或共同祖先非 maxnum,结果可能错误。例如,父子关系为 [[1,3],[3,4],[2,5]]maxnum=5,但小明和小宇无共同祖先,代码仍会输出错误结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值