剑指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.如输入的树中有指向父节点的指针,那么从两个输入节点开始,各自向上直到根节点是两个链表,相当于找链表的第一个公共节点。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 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)