找到二叉数中某两个节点的第一个共同祖先节点。这里给出了两种解法,分别是常规解法和递归解法。
常规解法:首先从root开始,自上而下,找到p节点的所有祖先节点,然后依据从下往上的顺序,判断每一个p的祖先节点是不是q的祖先节点,如果是的话,那么就是第一个共同祖先节点,返回
//判断root是不是q的祖先节点
bool isancestor(TreeNode *root, TreeNode* q) {
//root为NULL节点,终止递归,返回
if (root == NULL) {
return false;
}
//找到q节点,返回True,即root节点是q节点本身,也就是祖先
if (root->val == q->val) {
return true;
} else {
//如果root的左子树或者右子树是q的祖先结点,那么root也是q的祖先节点
return isancestor(root->left, q) || isancestor(root->right, q);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
stack<TreeNode*> nodes;
TreeNode* node = root;
//找到p的所有祖先结点,存入nodes
while (true) {
//判断node是不是p的祖先节点
if (isancestor(node, p)) {
nodes.push(node);
} else {
break;
}
//递归判断node的左子结点或者右子结点是不是p的祖先,如果是的话,就加入nodes
if (isancestor(node->left, p)) {
nodes.push(node->left);
node = node->left;
} else if (isancestor(node->right, p)) {
nodes.push(node->right);
node = node->right;
} else {
break;
}
}
//p结点本身也是祖先结点
if (node) {
nodes.push(node);
}
//判断p的所有祖先结点,是不是q的祖先结点,如果是,则返回
while (!nodes.empty()) {
node = nodes.top();
nodes.pop();
if (isancestor(node, q)) {
return node;
}
}
return NULL;
}
递归解法:
struct TreeNode {
int val;
TreeNode *left;
TreeNode *right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
//到达叶子节点,没有找到p节点或者q节点
if (root == NULL) {
return NULL;
}
//找到了p 节点或者q节点,返回
if (root->val == p->val || root->val == q->val) {
return root;
}
//在当前节点的左子树和右子树递归寻找p、q节点
TreeNode *left = lowestCommonAncestor(root->left, p, q);
TreeNode *right = lowestCommonAncestor(root->right, p, q);
//p、q节点一个在左子树,一个在右子树,那么共同祖先节点就是当前root节点
if (left && right) {
return root;
//p或q节点都在左子树
} else if (left) {
return left;
//p或q节点都在右子树
} else if (right) {
return right;
} else {
return NULL
}
}