lc310_最小高度树 【TED演讲】过度疲劳使我们失去创造力 Figma怎么导入字体 爱护身体,及时就医
Algorithm
lc310_最小高度树
思路:
以前都是做的树的最长边,先dfs最远再dfs回来。
这里最小高度应该就是: (之前最长边 + 1) / 2.
反向遍历的时候还要记录路径,拿出中间一个(最长长度为奇数)或者两个节点(最长长度为偶数)。
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
class Solution {
int max_depth;
int far_node;
int far_node1;
int far_node2;
vector<int> ans_path;
public:
// void dfs2(int node, int parent, vector<int> path, const vector<vector<int>>& nodes) {
// if (nodes[node].size() == 1 && node == far_node2) {
// path.push_back(far_node2);
// ans_path.assign(path.begin(), path.end());
// return ;
// }
// path.push_back(node);
// for (auto nxt : nodes[node]) {
// // 注意 parent 要使用
// if (nxt != parent) {
// dfs2(nxt, node, path, nodes);
// }
// }
// }
void dfs(int node, int parent, int depth, vector<int>& parent_path,
const vector<vector<int>>& nodes) {
if (nodes[node].size() == 1 && depth > max_depth) {
max_depth = depth;
far_node = node;
return ;
}
for (auto nxt : nodes[node]) {
// 注意parent使用
if (nxt != parent) {
parent_path[nxt] = node;
dfs(nxt, node, depth + 1, parent_path, nodes);
}
}
}
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
// 特例要考虑
if (n == 1) {
return {0};
}
// vector<vector<int>> nodes(n, vector<int>(n)); 不能一开始声明值。
vector<vector<int>> nodes(n);
for (auto& edge : edges) {
nodes[edge[0]].push_back(edge[1]);
nodes[edge[1]].push_back(edge[0]);
}
max_depth = 0;
far_node = -1;
far_node1 = -1;
far_node2 = -1;
vector<int> parent_path(n, -1);
dfs(0, -1, 0, parent_path, nodes);
far_node1 = far_node;
max_depth = 0;
dfs(far_node1, -1, 0, parent_path, nodes);
far_node2 = far_node;
// ans_path.clear();
// // 超出内存限制 70 / 71 个通过的测试用例
// vector<int> path;
// dfs2(far_node1, -1, path, nodes);
ans_path.clear();
parent_path[far_node1] = -1;
int y = far_node2;
while (y != -1) {
ans_path.emplace_back(y);
y = parent_path[y];
}
vector<int> ans;
int length = (max_depth + 1) / 2;
ans.push_back(ans_path[length]);
if (max_depth & 1) {
ans.push_back(ans_path[length - 1]);
}
return ans;
}
};
|
得了流感,38.9度发烧。写出来是错的(MLE),
还是看看题解吧。
题解也是dfs,bfs,思路和我的一样,但是实现了一个比较精妙的parents数组,所以比较好一点。
学习其中 parents 的精髓,其实就是把dfs的起始节点当成根。
看完病,发现在公司密闭环境得了流感痛苦3天…回家吃药后就借鉴题解AC出来了..
bfs,dfs
bfs
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
|
class Solution {
public:
int findLongestNode(int u, vector<int> & parent, vector<vector<int>>& adj) {
int n = adj.size();
queue<int> qu;
vector<bool> visit(n);
qu.emplace(u);
visit[u] = true;
int node = -1;
while (!qu.empty()) {
int curr = qu.front();
qu.pop();
node = curr;
for (auto & v : adj[curr]) {
if (!visit[v]) {
visit[v] = true;
parent[v] = curr;
qu.emplace(v);
}
}
}
return node;
}
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if (n == 1) {
return {0};
}
vector<vector<int>> adj(n);
for (auto & edge : edges) {
adj[edge[0]].emplace_back(edge[1]);
adj[edge[1]].emplace_back(edge[0]);
}
vector<int> parent(n, -1);
/* 找到与节点 0 最远的节点 x */
int x = findLongestNode(0, parent, adj);
/* 找到与节点 x 最远的节点 y */
int y = findLongestNode(x, parent, adj);
/* 求出节点 x 到节点 y 的路径 */
vector<int> path;
parent[x] = -1;
while (y != -1) {
path.emplace_back(y);
y = parent[y];
}
int m = path.size();
if (m % 2 == 0) {
return {path[m / 2 - 1], path[m / 2]};
} else {
return {path[m / 2]};
}
}
};
|
dfs
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
|
class Solution {
public:
void dfs(int u, vector<int> & dist, vector<int> & parent, const vector<vector<int>> & adj) {
for (auto & v : adj[u]) {
if (dist[v] < 0) {
dist[v] = dist[u] + 1;
parent[v] = u;
dfs(v, dist, parent, adj);
}
}
}
int findLongestNode(int u, vector<int> & parent, const vector<vector<int>> & adj) {
int n = adj.size();
vector<int> dist(n, -1);
dist[u] = 0;
dfs(u, dist, parent, adj);
int maxdist = 0;
int node = -1;
for (int i = 0; i < n; i++) {
if (dist[i] > maxdist) {
maxdist = dist[i];
node = i;
}
}
return node;
}
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if (n == 1) {
return {0};
}
vector<vector<int>> adj(n);
for (auto & edge : edges) {
adj[edge[0]].emplace_back(edge[1]);
adj[edge[1]].emplace_back(edge[0]);
}
vector<int> parent(n, -1);
/* 找到距离节点 0 最远的节点 x */
int x = findLongestNode(0, parent, adj);
/* 找到距离节点 x 最远的节点 y */
int y = findLongestNode(x, parent, adj);
/* 找到节点 x 到节点 y 的路径 */
vector<int> path;
parent[x] = -1;
while (y != -1) {
path.emplace_back(y);
y = parent[y];
}
int m = path.size();
if (m % 2 == 0) {
return {path[m / 2 - 1], path[m / 2]};
} else {
return {path[m / 2]};
}
}
};
|
拓扑法
然后题解中的拓扑法不断删除度为1的节点则是惊艳
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
|
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if (n == 1) {
return {0};
}
vector<int> degree(n);
vector<vector<int>> adj(n);
for (auto & edge : edges){
adj[edge[0]].emplace_back(edge[1]);
adj[edge[1]].emplace_back(edge[0]);
degree[edge[0]]++;
degree[edge[1]]++;
}
queue<int> qu;
vector<int> ans;
for (int i = 0; i < n; i++) {
if (degree[i] == 1) {
qu.emplace(i);
}
}
int remainNodes = n;
while (remainNodes > 2) {
int sz = qu.size();
remainNodes -= sz;
for (int i = 0; i < sz; i++) {
int curr = qu.front();
qu.pop();
for (auto & v : adj[curr]) {
if (--degree[v] == 1) {
qu.emplace(v);
}
}
}
}
while (!qu.empty()) {
ans.emplace_back(qu.front());
qu.pop();
}
return ans;
}
};
|
Review
【TED演讲】过度疲劳使我们失去创造力
我们不是机器,不会一直高效率,不要强求自己一直高效率,不要强求自己不会犯错。
不成功并不是因为你不努力,很可能是运气不好。
合理安排工作,及时休息,让自己变回有创造力的自己。
Tips
Figma怎么导入字体
Share
爱护身体,及时就医
最近在密闭办公室得了流感,痛了2.5天,实在扛不住了才去了医院,结果发现一直发烧38.9度..
所以希望大家在流感季节注意防止传染病,然后身体不适及时就医。
否则会浪费好几天时间感到痛苦。并且可能会让自己的生活一团糟,搞错很多很多东西,以及投资损失等等。