给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
例如,给定如下二叉树: root = [3,5,1,6,2,0,8,null,null,7,4].
示例 1:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。
示例 2:
输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出: 5
解释: 节点 5 和节点 4 的最近公共祖先是节点 5。因为根据定义最近公共祖先节点可以为节点本身。
说明:
这道题想要得到任意两个结点(a和b)的最近公共祖先节点,那么我们倘若将到
达两个结点的路径都列出来,那公共祖先结点一定在这两条路径上,且在最靠后的位
置,在对比倒着挨个查找就能得到结果。那我们怎么获得这个路径呢?
我们可以用2个栈来保存这两个结点的路径,每当遇到一个结点,我们就先将这个结点
先入栈(因为每个结点都有可能是最终路径上的结点),然后查看这个结点是否是
我们最终要找的那两个结点,如果是,则当前栈里的结点顺序就是我们想要的路
径,结束查找,如果不是,递归的去该结点的左子树和右子树里查找,如果都没
有找到,说明以该子树没有我们想要的结点,自然它肯定不在最终路径上,将其
出栈即可。
#include
#include
using namespace std;
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
//思路:
// 1.用两个栈分别记录到值a,b的路径
// 2.让两个栈当中多的那个栈出栈,直到两个栈size()相同
// 3.再同时出栈直到找到相同结点,相同结点即使最近祖先
class Solution {
public:
bool makePath(TreeNode* root, stack& s, TreeNode* point)
{
if (root == nullptr)
return false;
s.push(root);
if (root->val == point->val)
return true;
if (makePath(root->left, s, point) == true)
return true;
if (makePath(root->right, s, point) == true)
return true;
s.pop();//运行到这里说明当前递归下的左右子树都没有point结点,
//根结点不是最终路径上的结点,出栈即可。
return false;//向上层递归传达:我所在的树没有point结点
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
stack s1;
stack s2;
makePath(root, s1, p);//查找路径
makePath(root, s2, q);
if (s1.size() >= s2.size())//将两个栈弄成等长
{
while (s1.size() > s2.size())
{
s1.pop();
}
}
else
{
while (s2.size() > s1.size())
{
s2.pop();
}
}
while (s1.top() != s2.top())//倒着找最先重复的结点,就是最近的公共祖先
{
s1.pop();
s2.pop();
}
return s1.top();
}
};