剑指offer 学习笔记 树中两个节点的最低公共祖先

面试题68:树中两个节点的最低公共祖先。

可以先得到从根节点到这两个节点的路径,之后找出最后一个公共节点,代码中的树为:
在这里插入图片描述

#include <iostream>
using namespace std;

struct TreeNode {
    int m_nValue;
    vector<TreeNode*> m_chlidren;
};

bool GetNodePath(TreeNode* pRoot, TreeNode* pNode, vector<TreeNode*> &path) {
    if (pRoot == pNode) {
        return true;
    }

    bool found = false;
    path.push_back(pRoot);

    vector<TreeNode*>::iterator b = pRoot->m_chlidren.begin();
    while (!found && b != pRoot->m_chlidren.end()) {    
        found = GetNodePath(*b, pNode, path);
        ++b;
    }
    
    if (!found) {    // 以上循环结束时以pRoot为根节点的子树要么含pNode,要么不含,当不含时,将当前节点从路径中删除
        path.pop_back();
    }

    return found;
}

TreeNode* FindLastCommonNode(vector<TreeNode*> path1, vector<TreeNode*> path2) {
    vector<TreeNode*>::const_iterator b1 = path1.begin();
    vector<TreeNode*>::const_iterator b2 = path2.begin();

    TreeNode* res = nullptr;
    while (b1 != path1.end() && b2 != path2.end()) {
        if (*b1 != *b2) {
            return res;
        }
        res = *b1;
        ++b1;
        ++b2;
    }

    if (b2 == path2.end() && b1 == path1.end()) {
        return *(b1.end() - 1);
    }

    return nullptr;
}

TreeNode* FindLastCommonParent(TreeNode *pRoot, TreeNode *pNode1, TreeNode *pNode2) {
    if (pRoot == nullptr || pNode1 == nullptr || pNode2 == nullptr) {
        return nullptr;
    }

    vector<TreeNode*> path1;
    vector<TreeNode*> path2;
    GetNodePath(pRoot, pNode1, path1);
    GetNodePath(pRoot, pNode2, path2);

    return FindLastCommonNode(path1, path2);
}

int main() {
    TreeNode *Node1 = new TreeNode();
    TreeNode *Node2 = new TreeNode();
    TreeNode *Node3 = new TreeNode();
    TreeNode *Node4 = new TreeNode();
    TreeNode *Node5 = new TreeNode();
    TreeNode *Node6 = new TreeNode();
    TreeNode *Node7 = new TreeNode();
    TreeNode *Node8 = new TreeNode();
    TreeNode *Node9 = new TreeNode();
    TreeNode *Node10 = new TreeNode();
    
    Node1->m_nValue = 1;
    Node2->m_nValue = 2;
    Node3->m_nValue = 3;
    Node4->m_nValue = 4;
    Node5->m_nValue = 5;
    Node6->m_nValue = 6;
    Node7->m_nValue = 7;
    Node8->m_nValue = 8;
    Node9->m_nValue = 9;
    Node10->m_nValue = 10;

    Node1->m_chlidren.push_back(Node2);
    Node1->m_chlidren.push_back(Node3);
    Node2->m_chlidren.push_back(Node4);
    Node2->m_chlidren.push_back(Node5);
    Node4->m_chlidren.push_back(Node6);
    Node4->m_chlidren.push_back(Node7);
    Node5->m_chlidren.push_back(Node8);
    Node5->m_chlidren.push_back(Node9);
    Node5->m_chlidren.push_back(Node10);

    TreeNode* pRes = FindLastCommonParent(Node1, Node6, Node8);

    if (pRes) {
        cout << pRes->m_nValue << endl;
    } else {
        cout << "没有公共祖先。" << endl;
    }
}

以上解法不适合一个节点在另一个节点的路径上的情况。

相关题目:
1.如输入的树是二叉搜索树,可以从根节点开始比较值,如根节点值比两个数都大,那么最低公共祖先就在根节点的左子树中,如根节点值比这两个数都小,那么最低公共祖先就在根节点的右子树中,递归到一个节点值在两个输入的节点值之间时,这个节点就是结果。
2.如输入的树中有指向父节点的指针,那么从两个输入节点开始,各自向上直到根节点是两个链表,相当于找链表的第一个公共节点。

posted @   epiphanyy  阅读(7)  评论(0编辑  收藏  举报  
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示