From 5a9d218bcbcf6d6b0401533c7c4177bf509f9b63 Mon Sep 17 00:00:00 2001 From: Matej Focko Date: Sat, 24 Feb 2024 23:46:13 +0100 Subject: [PATCH] =?UTF-8?q?cpp:=20solve=20=C2=AB2092.=20Find=20All=20Peopl?= =?UTF-8?q?e=20With=20Secret=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Matej Focko --- cpp/find-all-people-with-secret.cpp | 87 ++++++++++++++++++++--------- 1 file changed, 62 insertions(+), 25 deletions(-) diff --git a/cpp/find-all-people-with-secret.cpp b/cpp/find-all-people-with-secret.cpp index 96721a7..7e6d2d3 100644 --- a/cpp/find-all-people-with-secret.cpp +++ b/cpp/find-all-people-with-secret.cpp @@ -1,51 +1,88 @@ #include -#include -#include +#include +#include +#include +#include #include class Solution { - void handle_previous_meeting(std::set &overall, - std::set ¤t) { - std::vector intersection; - std::set_intersection(current.begin(), current.end(), overall.begin(), - overall.end(), std::back_inserter(intersection)); + void process_timeslot(std::vector &knows, + const std::vector> &meetings) { + // Reconstruct the components for the same timeslot + // and also construct the source of secret + std::unordered_set sources; + std::unordered_map> neighbors; + for (const auto &[a, b] : meetings) { + if (knows[a]) { + sources.insert(a); + } + if (knows[b]) { + sources.insert(b); + } - if (!intersection.empty()) { - overall.insert(current.begin(), current.end()); + neighbors[a].push_back(b); + neighbors[b].push_back(a); } - current = {}; + // Constructing queue from iterators is allowed since C++23… + std::queue q; + for (const auto &p : sources) { + q.push(p); + } + + // Classic BFS + while (!q.empty()) { + int u = q.front(); + q.pop(); + + for (const auto &neighbor : neighbors[u]) { + if (knows[neighbor]) { + continue; + } + + knows[neighbor] = true; + q.push(neighbor); + } + } } public: std::vector findAllPeople(int n, std::vector> meetings, int firstPerson) { + // Sort the meetings by time std::sort(meetings.begin(), meetings.end(), [](const auto &l, const auto &r) { return l[2] < r[2]; }); - std::set knowers{0, firstPerson}; - - std::set current_meeting{}; - int timestamp = -1; + // Group meetings first + std::map>> groups; for (const auto &meeting : meetings) { auto a = meeting[0]; auto b = meeting[1]; auto t = meeting[2]; - if (t != timestamp) { - // handle the previous meeting - handle_previous_meeting(knowers, current_meeting); - timestamp = t; - } - - // just add the members and carry on - current_meeting.insert(a); - current_meeting.insert(b); + groups[t].emplace_back(a, b); } - handle_previous_meeting(knowers, current_meeting); - return std::vector(knowers.begin(), knowers.end()); + // Keep “knowers” in the bitset + std::vector knows(n, false); + knows[0] = true; + knows[firstPerson] = true; + + // Go through the groups + for (const auto &[time, meetings] : groups) { + process_timeslot(knows, meetings); + } + + // Reconstruct the list of people that know + std::vector all_people; + for (auto i = 0; i < n; ++i) { + if (knows[i]) { + all_people.push_back(i); + } + } + + return all_people; } };