题目链接:
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
题目描述:
给一棵树,找两结点的最近公共祖先。
3
/ \
5 1
/ \ / \
6 2 0 8
/ \
7 4
LCA of nodes 5 and 1 is 3
LCA of nodes 5 and 4 is 5
题目分析:
设置两个标记变量pFind,qFind,当递归从根结点往下找,如果没有找到root与p或q相等,就让ptr_p和ptr_q随root一起变化,如果找到结点与p,标记pFind找到,这样当继续往下找的时候,ptr_p就不再改变,除非又回到ptr_p的上一层,当pFind与qFind都标记找到时,就可以不断的返回上一层找公共祖先。因为pFind或qFind单个标记找到时,往下找ptr_p或ptr_q不会再改变,这样就保证了只有往上找即找祖先时,才会出现ptr_p与ptr_q相等的情况(即是之前ptr_q与ptr_p随root一起变化时)。
第二次:
隔了几个月又来写这道题了,温故而知新。其实在普通树里面找两个节点的最近公共祖先。假设对于一个节点,如果在它的右子树里面只找到了其中一个目标节点,而在它的左子树中没有找到另一个目标节点,那么当前节点就不是目标节点的最近公共祖先了,但是如果在它的左子树中找到另一个目标节点,那么当前节点就是目标节点的公共祖先了。
所以,我们可以从叶子节点向上,标记子树中出现目标节点的情况。若一个节点的左右子树都有标记,则当前节点就是目标节点。
代码:
class Solution {
public:
bool pFind=false;
bool qFind=false;
bool flag=false;
void findLowestCommonAncestor(TreeNode* root,TreeNode* &LCA, TreeNode* ptr_p, TreeNode* ptr_q, TreeNode* p, TreeNode* q){
if (root != NULL){
if (pFind && qFind){
return;
}
if (!pFind){
ptr_p = root;
}
if (!qFind){
ptr_q = root;
}
if (root == p){
pFind = true;
}
if (root == q){
qFind = true;
}
findLowestCommonAncestor(root->left,LCA, ptr_p, ptr_q, p, q);
findLowestCommonAncestor(root->right,LCA, ptr_p, ptr_q, p, q);
if (!flag && pFind && qFind && ptr_p == ptr_q){
flag = true;
LCA = ptr_p;
}
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
TreeNode* LCA = NULL;
findLowestCommonAncestor(root,LCA, root, root, p, q);
return LCA;
}
};
ps:太二了,写的时候还在想递归返回结点,结点岂不是要一直改变,咋把LCA返回,蠢哭,传个引用就好了啊。
第二次:
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!=NULL && right!=NULL){
return root;
}
return left==NULL? right:left;
}
};