I haven't written the codility question for a long time, so I have no time, and I am not very good at analyzing some questions. This question is interesting, and I have not provided a very strict proof.
Given a tree (undirected acyclic graph), start from a node and select as many nodes as possible from the start point to the destination node path, until all nodes are traversed. If there are as many nodes in the path from the start point to the two destination nodes, select a node with a smaller label as the destination node. Continue until all nodes are traversed. Which target nodes are selected in order?
For example, from 2, select 0 for the first time, and then 1 and 0 are changed to the experienced node.
Start from 0, select 6 for the second time, and then change 4 to the node that has been experienced.
Then, start from 6, select 3 for the third time, and then change 3 to the experienced node.
Then, start from 3 and select 5 for the last time, and then change 5 to the experienced node.
Output [2, 0, 6, 3, 5]
The function header is vector <int> solution (int K, vector <int> & T );
K indicates the start number, and (I, T [I]) indicates an edge of the tree.
Variable range node count N, [1 .. 90,000], telement range [0 .. N-1]
Time complexity O (N) and space complexity O (n) are required ).
Analysis: I don't think I can solve this problem perfectly because I didn't provide a strict proof. First, the target node must be a leaf, which is more effective intuitively with deeper depth. So I sorted the leaves by leaf depth from large to small. If the depth is the same, I put the leaves with a small number in front. Define the weight value for the leaves in this order. This value is the number of new nodes on the last access path (this requires strict proof ). The weight value is defined as follows, and continues to walk to the father along the leaves until the first marked node stops. The number of nodes in this path is used as the weight of the leaf. In addition, the nodes in this path are not marked. The key issue is that the weights of each leaf should be calculated according to the previous order (because the order affects the weights of the leaves ). The intuitive feeling is that if the two leaves are on one forks, it is obvious that the deep nodes are accessed first. If they are not on the same forks, there is no loss. Finally, sorting the leaves again based on this weight is the desired result. In order to satisfy the time complexity, I used base sorting and wrote a help function to complete sorting.
The general idea is:
(1) first DFS, get the depth of each leaf and the father of each node
(2) Base sorting of all leaves by Depth
(3) Calculate the weight of each leaf in an ordered Order (complexity is equivalent to traversing the tree because it is traversed up the leaf)
(4) sort the base number of the leaves based on the calculated weights to obtain the final result.
Final code:
// you can also use includes, for example:// #include <algorithm>void help(int n, vector<pair<int,int> > &v) { // (id, weight) vector<vector<int> > have; have.resize(n); for (int i = 0; i < v.size(); ++i) { have[v[i].first].push_back(v[i].second); } v.clear(); for (int i = 0; i < n; ++i) { for (int j = 0; j < have[i].size(); ++j) { v.push_back(make_pair(i, have[i][j])); } } have.clear(); have.resize(n); for (int i = 0; i < v.size(); ++i) { have[v[i].second].push_back(v[i].first); } v.clear(); for (int i = n - 1; i >= 0; --i) { for (int j = 0; j < have[i].size(); ++j) { v.push_back(make_pair(have[i][j] , i)); } }}void dfs(int x,int p,int d,vector<int> &depth, vector<int> &parent,vector<vector<int> > & con) { parent[x] = p; depth[x] = d; for (int i = 0; i < con[x].size(); ++i) { if (con[x][i] != p) { dfs(con[x][i], x, d + 1, depth, parent, con); } } }vector<int> solution(int K, vector<int> &T) { // write your code in C++98 vector<vector<int> > con; int n = T.size(); con.resize(n); for (int i = 0; i < n; ++i) { if (T[i] != i) { con[i].push_back(T[i]); con[T[i]].push_back(i); } } vector<int> parent, depth; depth.resize(n); parent.resize(n); dfs(K, -1, 0, depth, parent, con); vector<pair<int,int> > v; for (int i = 0; i < n; ++i) { if ((i != K) && (con[i].size() == 1)) { //leaf v.push_back(make_pair(i, depth[i])); } } help(n,v); vector<bool> mark; mark.resize(n, false); for (int i = 0; i < v.size(); ++i) { int x = -1; for (int j = v[i].first; (j >= 0) && (!mark[j]); ++x, j = parent[j]) { mark[j] = true; } v[i].second = x; } help(n,v); vector<int> result; result.push_back(K); for (int i = 0; i < v.size(); ++i) { result.push_back(v[i].first); } return result;}