题目
给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。
最近公共祖先的定义为:“对于有根树 T 的两个节点 p、q,最近公共祖先表示为一个节点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
示例
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出:3
解释:节点 5 和节点 1 的最近公共祖先是节点 3 。
输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4
输出:5
解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。
输入:root = [1,2], p = 1, q = 2 输出:1
解决方法
从根节点开始先对二叉树进行遍历,利用哈希表存储所有节点的父节点。
后我们就可以利用节点的父节点信息从 p 结点开始不断向上追溯,并用vector记录当前追溯的节点是否已经访问过(想象为染色)。再从 q 节点开始不断向上追溯,如果碰到已经访问过的节点,那么这个节点就是我们要找的最近公共祖先。
时空复杂度均为O(n),其中n为二叉树的节点个数。
代码实现
/**
* 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:
map<TreeNode*,TreeNode*> record; //用于记录各个节点的父节点
map<TreeNode*, bool> vis;
void preorder(TreeNode* root){ //边进行遍历边记录各个节点的父节点
if(root == NULL){
return;
}
record[root->left] = root;
record[root->right] = root;
preorder(root->left);
preorder(root->right);
return;
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
record[root] = NULL;
preorder(root);
while(p != NULL){ //对p进行追溯
vis[p] = true; //记录节点是否被访问过
p = record[p];//追溯到p的父节点
}
while (q != nullptr) { //对q进行追溯
if (vis[q]) return q; //找到了公共祖先
q = record[q]; //追溯到q的父节点
}
return nullptr;
}
};