Medium
Amount of Time for Binary Tree to Be Infected — C++
Full explanation · Time O(n) · Space O(h)
// Time: O(n)
// Space: O(h)
// iterative dfs, tree dp
class Solution {
public:
int amountOfTime(TreeNode* root, int start) {
const auto& iter_dfs = [&]() {
int result = -1;
using RET = pair<int, int>;
RET ret = {-1, -1};
vector<tuple<int, TreeNode *, shared_ptr<RET>, shared_ptr<RET>, RET *>> stk;
stk.emplace_back(1, root, nullptr, nullptr, &ret);
while (!empty(stk)) {
auto [step, curr, left, right, ret] = stk.back(); stk.pop_back();
if (step == 1) {
if (!curr) {
continue;
}
auto left = make_shared<RET>(-1, -1), right = make_shared<RET>(-1, -1);
stk.emplace_back(2, curr, left, right, ret);
stk.emplace_back(1, curr->right, nullptr, nullptr, right.get());
stk.emplace_back(1, curr->left, nullptr, nullptr, left.get());
} else if (step == 2) {
int d = -1;
if (curr->val == start) {
d = 0;
result = max(left->first, right->first) + 1;
} else if (left->second >= 0) {
d = left->second + 1;
result = max(result, right->first + 1 + d);
} else if (right->second >= 0) {
d = right->second + 1;
result = max(result, left->first + 1 + d);
}
*ret = make_pair(max(left->first, right->first) + 1, d); // [height, dist_to_start]
}
}
return result;
};
return iter_dfs();
}
};
// Time: O(n)
// Space: O(h)
// dfs, tree dp
class Solution2 {
public:
int amountOfTime(TreeNode* root, int start) {
int result = -1;
const function<pair<int, int>(TreeNode *)> dfs = [&](TreeNode *curr) {
if (!curr) {
return make_pair(-1, -1);
}
const auto& left = dfs(curr->left);
const auto& right = dfs(curr->right);
int d = -1;
if (curr->val == start) {
d = 0;
result = max(left.first, right.first) + 1;
} else if (left.second >= 0) {
d = left.second + 1;
result = max(result, right.first + 1 + d);
} else if (right.second >= 0) {
d = right.second + 1;
result = max(result, left.first + 1 + d);
}
return make_pair(max(left.first, right.first) + 1, d); // [height, dist_to_start]
};
dfs(root);
return result;
}
};
// Time: O(n)
// Space: O(n)
// bfs
class Solution3 {
public:
int amountOfTime(TreeNode* root, int start) {
const auto& bfs = [](const auto& root) {
unordered_map<int, vector<int>> adj;
vector<TreeNode *> q = {root};
while (!empty(q)) {
vector<TreeNode *> new_q;
for (const auto& u : q) {
for (const auto& v : {u->left, u->right}) {
if (!v) {
continue;
}
adj[u->val].emplace_back(v->val);
adj[v->val].emplace_back(u->val);
new_q.emplace_back(v);
}
}
q = move(new_q);
}
return adj;
};
const auto& bfs2 = [](const auto& adj, const auto& start) {
int result = -1;
vector<int> q = {start};
unordered_set<int> lookup = {start};
while (!empty(q)) {
vector<int> new_q;
for (const auto& u : q) {
if (!adj.count(u)) {
continue;
}
for (const auto& v : adj.at(u)) {
if (lookup.count(v)) {
continue;
}
lookup.emplace(v);
new_q.emplace_back(v);
}
}
q = move(new_q);
++result;
}
return result;
};
const auto& adj = bfs(root);
return bfs2(adj, start);
}
};