方法一:逐个比较节点
/**
* 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* res;
bool flag=0; //root是否为其中一个节点
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
findCommomRoot(root,p,q);
return res;
}
int findCommomRoot(TreeNode* root, TreeNode* p, TreeNode* q){
if( root==nullptr)
return 0;
int l=findCommomRoot(root->left,p,q);
int r=findCommomRoot(root->right,p,q);
if(root==p || root==q){
if(l || r) //一个节点是另一个节点的子节点
res=root;
return 1; //另一个节点不是子节点,那么返回1
}
if(l && r) // 分别在左右子树时
res=root;
return l || r;
}
};
方法二:利用二叉搜索树性质,利用大小关系,最近公共节点一定是大于一个,小于一个。可以分别用迭代,递归的方法写。以下为迭代
class Solution {
public:
TreeNode* res;
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
while(root!=nullptr){
if(root->val<p->val && root->val<q->val ) //值都比root大,说明都在右子树里
root=root->right;
else if(root->val>p->val && root->val>q->val ) //值都比root小,说明都在左子树里
root=root->left;
else
break;
}
return root;
//只有最近根节点才会满足一大一小,或者是等于某一个节点
}
};
方法三:巧妙
class Solution {
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
if(root == null) return null; // 如果树为空,直接返回null
if(root == p || root == q) return root; // 如果 p和q中有等于 root的,那么它们的最近公共祖先即为root(一个节点也可以是它自己的祖先)
TreeNode left = lowestCommonAncestor(root.left, p, q); // 递归遍历左子树,只要在左子树中找到了p或q,则先找到谁就返回谁
TreeNode right = lowestCommonAncestor(root.right, p, q); // 递归遍历右子树,只要在右子树中找到了p或q,则先找到谁就返回谁
if(left == null) return right; // 如果在左子树中 p和 q都找不到,则 p和 q一定都在右子树中,右子树中先遍历到的那个就是最近公共祖先(一个节点也可以是它自己的祖先)
else if(right == null) return left; // 否则,如果 left不为空,在左子树中有找到节点(p或q),这时候要再判断一下右子树中的情况,如果在右子树中,p和q都找不到,则 p和q一定都在左子树中,左子树中先遍历到的那个就是最近公共祖先(一个节点也可以是它自己的祖先)
else return root; //否则,当 left和 right均不为空时,说明 p、q节点分别在 root异侧, 最近公共祖先即为 root
}
}
方法四:k个子节点的公共祖先
利用k来计数,遇到一个子节点的值就-1
class Solution {
private TreeNode res;
private int k;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
k = 2;
dfs(root, p, q);
return res;
}
private void dfs(TreeNode note, TreeNode p, TreeNode q) {
if (note == null || k == 0) return;
int kOld = k;
if (note.val == p.val || note.val == q.val) k--;
dfs(note.left, p, q);
dfs(note.right, p, q);
if (kOld == 2 && k == 0 && res == null)
res = note;
}
}