题目描述
给你一些区域列表 regions ,每个列表的第一个区域都包含这个列表内所有其他区域。
很自然地,如果区域 X 包含区域 Y ,那么区域 X 比区域 Y 大。
给定两个区域 region1 和 region2 ,找到同时包含这两个区域的 最小 区域。
如果区域列表中 r1 包含 r2 和 r3 ,那么数据保证 r2 不会包含 r3 。
数据同样保证最小公共区域一定存在。
示例 1:
输入:
regions = [[“Earth”,“North America”,“South America”],
[“North America”,“United States”,“Canada”],
[“United States”,“New York”,“Boston”],
[“Canada”,“Ontario”,“Quebec”],
[“South America”,“Brazil”]],
region1 = “Quebec”,
region2 = “New York”
输出:“North America”
提示:
- 2 <= regions.length <= 10^4
- region1 != region2
- 所有字符串只包含英文字母和空格,且最多只有 20 个字母。
解题思路
这是13场双周赛的B题,知道是LCA,可是百度了还是不会做,我可能是个弱智
- 讨论区看到的题解,代码简洁高效,绝活!
- 这个题看起来难点就是在怎么构建这一课数,这里用数组来模拟,用了两个map来准确定位,很棒
- LCA的思路很简单,知道深度就可以一直往上**x = TN[x].fa;**就行了
struct node {
string data;
int depth;
int fa;
vector<int> chi;
}TN[100001];
class Solution {
public:
map<string, int> m;
map<int, string> m2;
int msize = 0;
string findSmallestRegion(vector<vector<string>>& regions, string region1, string region2) {
TN[1].depth = 0;
TN[1].fa = 1;
for (int i = 0; i < regions.size(); i++) {
string a = regions[i][0];
if (m[a] == 0) {
msize++;
m[a] = msize;
m2[msize] = a;
}
TN[m[a]].data = regions[i][0];
for (int j = 1; j < regions[i].size(); j++) {
string b = regions[i][j];
if (m[b] == 0) {
msize++;
m[b] = msize;
m2[msize] = b;
}
TN[m[b]].data = regions[i][j];
TN[m[a]].chi.push_back(m[b]);
TN[m[b]].fa = m[a];
TN[m[b]].depth = TN[m[a]].depth + 1;
}
}
int x = m[region1];
int y = m[region2];
while (TN[x].depth < TN[y].depth) {
y = TN[y].fa;
}
while (TN[x].depth > TN[y].depth) {
x = TN[x].fa;
}
while (1) {
if (x == y) break;
x = TN[x].fa;
y = TN[y].fa;
}
return m2[x];
}
};