0%

236.二叉树的最近公共祖先

236.二叉树的最近公共祖先

题目描述:

给出一棵二叉树,找出指定两个节点的最近公共祖先(LCA)。

数据范围:
$2\le n \le 10^5$

题解:

由于只查询一组,所以没什么优化的必要。直接暴力就行。

如果查询多组,就需要使用倍增法,RMQ法或者Tarjan了。其中tarjan是离线算法,其他两个是在线算法,一般使用倍增比较好写,比较简单。

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Solution {
public:
unordered_map<TreeNode*, TreeNode*> mp;
unordered_set<TreeNode*> st;
void dfs(TreeNode* root, TreeNode* fa)
{
if(root == nullptr) return;
mp[root] = fa;
dfs(root->left, root);
dfs(root->right, root);
}
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
dfs(root, nullptr);
while(p)
{
st.insert(p);
p = mp[p];
}
while(q)
{
if(st.count(q)) return q;
q = mp[q];
}
return nullptr;
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const static int INF = 0x3f3f3f3f;
TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q)
{
if (root == nullptr || root == p || root == q)
return root;
TreeNode *left = lowestCommonAncestor(root->left, p, q);
TreeNode *right = lowestCommonAncestor(root->right, p, q);
// 先看左右子树是否包含
if (left == nullptr && right == nullptr)
return nullptr;
if (left && right)
return root;
if (left)
return left;
if (right)
return right;
return nullptr;
}
};

倍增法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
class Solution
{
public:
const static int maxn = 1e5 + 10;
const static int maxm = 1e5 + 10;
const static int INF = 0x3f3f3f3f;
unordered_map<TreeNode *, unordered_map<int, TreeNode *>> fa;
unordered_map<TreeNode *, int> depth;
void dfs(TreeNode *root, TreeNode *p, int dep)
{

if (root == nullptr)
return;
fa[root][0] = p;
depth[root] = dep;
dfs(root->left, root, dep + 1);
dfs(root->right, root, dep + 1);
}

void build()
{
for (int k = 1; k < 17; ++k)
{
for (auto &root : depth)
{
fa[root.first][k] = fa[fa[root.first][k - 1]][k - 1];
}
}
}

TreeNode *query(TreeNode *p, TreeNode *q)
{
if (depth[p] < depth[q])
swap(p, q);
int tmp = depth[p] - depth[q];
for (int i = 17; i >= 0; --i)
{
if (tmp >= (1 << i))
{
p = fa[p][i];
tmp -= (1 << i);
}
}
if (p == q)
return p;
for (int i = 17; i >= 0; --i)
{
if (depth[p] >= (1 << i))
{
if (fa[p][i] != fa[q][i])
{
p = fa[p][i];
q = fa[q][i];
}
}
}
return fa[p][0];
}
TreeNode *lowestCommonAncestor(TreeNode *root, TreeNode *p, TreeNode *q)
{
dfs(root, nullptr, 0);
build();
return query(p, q);
}
};