本题来自leetcode中 236. 二叉树的最近公共祖先 - 力扣(LeetCode)
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)
本题思路:找到某一节点的所有祖先,按照从根到最近祖先顺序入栈,然后对比两个节点入栈中所有祖先数据即可。
如果要找7和8的最近公共祖先,首先将7节点的所有祖先入栈352,然后将8节点的所有祖先入栈31,因为两个节点所在高度可能不一致,所以先将长的栈出栈直到两个栈长度相等。然后一一比较,直到相等,得到最近公共祖先是3。
如果要找6和4的最近公共祖先,首先将6节点的所有祖先入栈35,然后将4节点的所有祖先入栈352,因为两个节点所在高度可能不一致,所以先将长的栈出栈直到两个栈长度相等。然后一一比较,直到相等,得到最近公共祖先是5。
具体代码实现如下:
首先是一个子函数,获取路径。
用节点7举例,若要找到节点7,从3开始,压栈3,走左子树5,然后压栈5,走左子树6,压6,6左子树为nullptr 返回 false。然后走6右子树,6右子树为nullptr返回false,弹出6。然后走5的右子树2,压2,走2的左子树压7,找到节点7,然后依次返回true到2 返回true到5 返回true到3。
bool GetPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& path)
{
if(root == nullptr)
return false;
path.push(root);
if(root == x)
return true;
if(GetPath(root->left,x,path))
return true;
if(GetPath(root->right,x,path))
return true;
path.pop();
return false;
}
如题1 得到7的路径为3527,8的节点为318,首先弹出7节点栈中的7。然后两个栈同时弹出数据,直到相等为3。
while(path1.size() != path2.size())
{
if(path1.size() > path2.size())
path1.pop();
else
path2.pop();
}
while(path1.top() != path2.top())
{
path1.pop();
path2.pop();
}
总代码如下
class Solution {
public:
bool GetPath(TreeNode* root,TreeNode* x,stack<TreeNode*>& path)
{
if(root == nullptr)
return false;
path.push(root);
if(root == x)
return true;
if(GetPath(root->left,x,path))
return true;
if(GetPath(root->right,x,path))
return true;
path.pop();
return false;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q)
{
stack<TreeNode*> path1,path2;
GetPath(root,p,path1);
GetPath(root,q,path2);
while(path1.size() != path2.size())
{
if(path1.size() > path2.size())
path1.pop();
else
path2.pop();
}
while(path1.top() != path2.top())
{
path1.pop();
path2.pop();
}
return path1.top();
}
};