236. Lowest Common Ancestor of a Binary Tree
思路:
题目中描述公共祖先定义为,p,q的共同且深度最深的祖先。就是最靠近p,q的祖先节点。
那么我们应该判断每个节点的子树是否有p,q,如果一个节点都有p,q那么这个点就是公共祖先。而且我们从底向上遍历,能得到的最深的深度了。
我们 通过这个条件
(left_son&&right_son) || ((root->valq->val||root->valp->val)&&(left_son||right_son))
第一个条件是用来判断该节点的左右子树是否有p,q。后面的一个条件是用来判断q或p是否作为公共祖先的条件,即root和q或p一个val相同并且另一个在该节点子树下。
/**
* 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 {
private:
TreeNode* res;
public:
bool dfs(TreeNode* root, TreeNode* p, TreeNode* q){
if(root==NULL) return false;
bool lc=dfs(root->left,p,q);
bool rc=dfs(root->right,p,q);
if((lc&&rc)||((root->val==p->val||root->val==q->val)&&(lc||rc))){
res = root;
}
return lc||rc||(root->val==q->val||root->val==p->val);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root,p,q);
return res;
}
};
另外一种是通过hash表来记录所有节点的父亲节点,然后将p不断往上移动到其父亲节点并且还要通过hash表来记录这个节点是否被访问,因为root父亲节点是NULL,所以当移动到root就结束,然后在移动q,循环条件是q所指的节点没有被访问过,当该节点被访问就退出循环并返回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 {
private:
unordered_map<int,TreeNode*> fa;
unordered_map<int,bool> visited;
public:
void dfs(TreeNode* root){
if(root->left!=NULL){
fa[root->left->val]=root;
dfs(root->left);
}
if(root->right!=NULL){
fa[root->right->val]=root;
dfs(root->right);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
fa[root->val]=NULL;
dfs(root);
while(p!=NULL){
visited[p->val]=true;
p=fa[p->val];
}
while(visited[q->val]!=true){
visited[q->val]=true;
q=fa[q->val];
}
return q;
}
};