题目链接:leetcode.
递归,返回值为当前节点的子树是否包含p或q
1.当前节点为空,则一定不包含,返回false
2.当前节点的左右子树都为true,或者,当前节点是p或q 且左右子树有一个为true,则当前节点就是最小公共子节点
3.当前节点的子树有true,则返回true,或者当前节点是p或q,也返回true
注意:找到的ans是最小公共祖先,因为从叶子节点往上找的,一定是深度最大的,而且找到之后,不会被别的节点刷新,因为ans的子树已经包括了p和q,而ans只能提供一个true值,所以再也满足不了if条件了
时间复杂度 O(n)每个节点都遍历一次
空间复杂度 O(n)递归调用栈的深度,最差条件下是一个链
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
/*
/*
执行用时:20 ms, 在所有 C++ 提交中击败了72.05%的用户
内存消耗:13.8 MB, 在所有 C++ 提交中击败了96.35%的用户
*/
class Solution {
public:
TreeNode* ans;
bool dfs(TreeNode* root, TreeNode* p, TreeNode* q)
{
if(root == nullptr)
return false;
bool lchild = dfs(root->left, p, q);
bool rchild = dfs(root->right, p, q);
if((lchild && rchild) || ((root == q || root == p) && (lchild || rchild)))
ans = root;
return lchild || rchild || (root == p) || (root == q);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, p, q);
return ans;
}
};
使用哈希表存储每个节点的父节点地址(因为每个节点的值仅出现一次)
1.遍历树,对于碰到的每一个节点,存储<value, &parent>
2.搜索p的parent,直到root,将访问过的节点置为true
3.搜索q的parent,碰到第一个被访问过的节点,就是最小公共祖先
O(n) O(n)
/*
执行用时:32 ms, 在所有 C++ 提交中击败了16.34%的用户
内存消耗:17.4 MB, 在所有 C++ 提交中击败了5.89%的用户
*/
class Solution {
public:
unordered_map<int, TreeNode*> map;
void dfs(TreeNode* root)
{
if(root == nullptr)
{
return;
}
if(root->left)
{
map[root->left->val] = root;
dfs(root->left);
}
if(root->right)
{
map[root->right->val] = root;
dfs(root->right);
}
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
map[root->val] = NULL;
dfs(root);
set<int> visit;
while(p)
{
visit.insert(p->val);
p = map[p->val];
}
while(q)
{
if(visit.count(q -> val))
{
return q;
}
q = map[q -> val];
}
return NULL;
}
};
本文介绍两种寻找二叉树中两个节点的最小公共祖先的方法:递归和使用哈希表记录父节点。递归方法通过判断当前节点的子树是否包含目标节点来确定公共祖先;哈希表方法则先存储每个节点的父节点,再从目标节点向上查找共同路径。
397

被折叠的 条评论
为什么被折叠?



