【LeetCode 310】 310. Minimum Height Trees题解(记忆化搜索)
题目
一棵树以任意一结点为根都可以形成一棵树,找出形成树高度最小的所有根节点。看似
O
(
n
2
)
O(n^2)
O(n2)能过,实际上过不了,得考虑
O
(
n
?
log
?
n
O(n\cdot \log{n}
O(n?logn或者
O
(
n
)
O(n)
O(n)的思路。
解题思路
- 假设以结点
x
x
x为根,
x
x
x有
i
?
?
?
j
i···j
i???j若干子结点,若干子节点为根形成的树高度依次为
H
i
?
?
?
H
j
H_i···H_j
Hi????Hj?。
- 则以
x
x
x为根的树的高度为所有子节点最大高度+1=
m
a
x
(
H
i
,
?
?
?
,
H
j
)
+
1
max(H_i,···,H_j)+1
max(Hi?,???,Hj?)+1。
- 对于任何一个结点,其子节点方向一旦搜索过则可以直接获取存储的高度而不用再次搜索。(记忆化搜索)
- 所以达到任何一个结点能够
O
(
1
)
O(1)
O(1)获取到其所有子节点的高度,即计算出任何一个结点为根的高度,只需要每条边双向都遍历一遍,遍历次数为
2
?
n
2\cdot n
2?n,时间复杂度为
O
(
n
)
O(n)
O(n)。
Code
class Solution {
public:
int minHeight = INT_MAX;
vector<int> ans;
int dfs(int n, vector<pair<int,int>> v[], int pre, bool* visit){
visit[pre] = true;
int height = 1;
for(int i = 0;i < v[pre].size(); ++i){
int nxt = v[pre][i].first;
if(v[pre][i].second == INT_MAX and !visit[nxt]){
v[pre][i].second = dfs(n,v,nxt,visit)+1;
height = max(height,v[pre][i].second);
}else if(!visit[nxt]){
for(int j = 0;j < v[nxt].size(); ++j){
if(v[nxt][j].first != pre){
v[pre][i].second = max(v[pre][i].second,v[nxt][j].second+1);
height = max(height,v[pre][i].second);
}
}
if(v[nxt].size() == 1){
v[pre][i].second = 2;
height = max(height,v[pre][i].second);
}
if(ans.size() > 0 and height > minHeight) return height;
}
if(ans.size() > 0 and height > minHeight) return height;
}
return height;
}
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
vector<pair<int,int>> v[n];
for(auto x:edges){
v[x[0]].push_back({x[1],INT_MAX});
v[x[1]].push_back({x[0],INT_MAX});
}
bool visit[n];
for(int i = 0;i < n; ++i){
memset(visit,false,sizeof(visit));
int x = dfs(n,v,i,visit);
if(x == minHeight){
ans.push_back(i);
}else if(x < minHeight) {
ans.clear();
ans.push_back(i);
minHeight = x;
}
}
return ans;
}
};
|