leetcode-236. 二叉树的最近公共祖先
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例 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 。因为根据定义最近公共祖先节点可以为节点本身。
示例 3:
输入:root = [1,2], p = 1, q = 2
输出:1
提示:
- 树中节点数目在范围
[2, 105]
内。 -109 <= Node.val <= 109
- 所有
Node.val
互不相同
。 p != q
p
和q
均存在于给定的二叉树中。
解法一(后序遍历非递归)
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == NULL) return NULL;
stack<TreeNode*> S;
S.push(root); // 根节点入栈
TreeNode* pre = NULL; // 前驱结点
TreeNode* cur = root; // 当前遍历结点
bool flag_p = false;
bool flag_q = false;
stack<TreeNode*> ancestor_p;
stack<TreeNode*> ancestor_q;
while((cur || !S.empty()) && (flag_p == false || flag_q == false)){
if(cur){ // 沿左孩子依次入栈
S.push(cur);
cur = cur->left;
}
else{
cur = S.top(); // 栈顶元素
if(cur->right && pre != cur->right) //右孩子存在且未遍历
cur = cur->right; // 转入右子树执行沿左孩子依次入栈操作
else{
if(cur == p){
flag_p = true;
ancestor_p = S; // 复制栈
}
if(cur == q){
flag_q = true;
ancestor_q = S; // 复制栈
}
S.pop();
pre = cur; // 更新pre
cur = NULL; // 将p置为NULL,保证接下来继续执行栈顶元素判定
}
}
}
// 将两个栈依次对比,逐一匹配,第一个找到的公共节点即最近公共祖先
vector<TreeNode*> a_p;
vector<TreeNode*> a_q;
int lenp = ancestor_p.size();
int lenq = ancestor_q.size();
for(int i = 0;i <lenp;i++){
cur = ancestor_p.top();
ancestor_p.pop();
a_p.push_back(cur);
}
for(int j = 0; j <lenq;j++){
cur = ancestor_q.top();
ancestor_q.pop();
a_q.push_back(cur);
}
for(int i = 0;i < lenp;i++){
for(int j = 0;j<lenq;j++){
if(a_p[i] == a_q[j])
return a_q[j];
}
}
return NULL;
}
};
递归
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(root == NULL || root == p || root == q)
return root;
TreeNode* left = lowestCommonAncestor(root->left,p,q);
TreeNode* right = lowestCommonAncestor(root->right,p,q);
if(left&&right) return root; // 左右子树都不为空,则返回根节点
//* 左边存在,那么右边肯定为空,
//* 右边存在,那么左边肯定为空,
return left? left:right;
}
};