LeetCode 236 Lowest Common Ancestor of a Binary Tree
概述
https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
注意子节点没有父指针哦。
递归法
根节点肯定是其共同祖先,一直向下直到子节点都不是共同祖先。
好了,现在我们要如何判断子节点是否是共同祖先?只能递归了。
要注意节点本身也是其父节点。
递归套递归,时间复杂度爆炸。
class Solution {
public:
TreeNode* ans;
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
helper(root, p, q);
return ans;
}
void helper(TreeNode* root, TreeNode* p, TreeNode* q) {
ans = root;
if (isCommonAncestor(root->left, p, q)) {
helper(root->left, p, q);
}
if (isCommonAncestor(root->right, p, q)) {
helper(root->right, p, q);
}
}
bool isCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
return isAncestor(root, p) && isAncestor(root, q);
}
bool isAncestor(TreeNode* root, TreeNode* p) {
if (!root) return false;
if (root == p) return true;
if (root->left == p || root->right == p) return true;
return isAncestor(root->left, p) || isAncestor(root->right, p);
}
};
一个可以优化的地方是,对判断节点是否是 p 和 q 的祖先节点可以做一下缓存。
更加直接的递归法
https://mp.weixin.qq.com/s/9RKzBcr3I592spAsuMH45g
从下往上看,从 p 出发,将其父节点做标记,q 同理,则自下向上第一个有双重标记的节点即最近共同祖先。
那要怎么自下向上嘞?后续遍历!
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (!root) return nullptr;
if (root == p || root == q) return root;
auto l = lowestCommonAncestor(root->left, p, q);
auto r = lowestCommonAncestor(root->right, p, q);
if (l != nullptr && r != nullptr) { // both are marked, which means root is a common ancestor
return root;
}
if (l == nullptr && r == nullptr) { // which means root is not ancestor of both nodes
return nullptr;
}
return l ? l : r; // root is only a ancestor of one of them, we should mark root
}
};
这个递归函数的返回值有两种,因此不好理解。
其实可以这样理解,前期用作布尔值,后期兼顾用来传递结果。
这也是为啥我们不能随便 return 一个非 null 值来进行标记。