面试时候如果遇到这种题,要问清楚面试官,是普通的树还是二叉树,如果是二叉树是不是二叉排序树?如果是普通的树有没有指向父节点的指针?
leetcode:235. 二叉搜索树的最近公共祖先
利用二叉搜索树的特性,对于这个性质,如果从下往上找,想根据每个结点找到他们的祖先再比较就很麻烦,直接根据二叉搜索树左<中<右的特性,从上往下进行查找。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root) return root;
while(1){
if(root->val < min(p->val,q->val)){
root = root->right;
}
else if(root->val > max(p->val,q->val)){
root = root->left;
}
else break;
}
return root;
}
};
leetcode:236.二叉树的最近公共祖先
递归,看当前结点是否为空,若为空则直接返回;若为p或q中的任意一个,直接返回当前结点。否则最近公共祖先要么是在当前结点的左子树上,或者在当前结点的右子树上。
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if(!root || root == q || root == p) return root;
TreeNode* left = lowestCommonAncestor(root->left,p,q);
if(left && left != q && left != p) return left;//优化步骤
TreeNode* right = lowestCommonAncestor(root->right,p,q);
if(left && right) return root;
return left?left:right;
}
};
优化:当p和q同时为于左子树中,而且返回的结点并不是p或q,那么就是p和q的最小父结点了,已经求出来了,就不用再对右结点调用递归函数了。(为什么呢?为什么要并且不是p或者q,如果要查找的是5,7的公共祖先)
补充:如果要查找的结点不在二叉树中呢?如何在二叉树、BST中查找某个结点?
仔细想想这个求最近公共祖先其实和求相交链表是一个问题。
如果这个树不是一个二叉树,是一个普通的树?但是包含指向父节点的指针,或者不包含指向父节点的指针怎么解决?
如果包含指向父节点的指针,那么可以根据某个节点一直向上去找,找到根节点,可以看做是一个求相交链表的问题;如果不包含父节点的指针,在遍历的时候用一个栈来保存当前路径上的所有节点,转换成找两个节点的最后一个公共节点。