LeetCode/cpp/greatest-common-divisor-traversal.cpp
Matej Focko c446face87
cpp: add «2709. Greatest Common Divisor Traversal»
Signed-off-by: Matej Focko <mfocko@redhat.com>
2024-02-25 23:29:38 +01:00

158 lines
3.4 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <algorithm>
#include <cmath>
#include <unordered_map>
#include <vector>
namespace {
struct factors_iterator {
factors_iterator() : f(-1) {}
factors_iterator(int f, int n) : f(f), n(n), upper(std::sqrt(n)) {}
auto operator!=(const factors_iterator &other) const -> bool {
return f != other.f;
}
auto operator*() const -> int { return f; }
auto operator++() -> factors_iterator & {
// f yielded a prime
if (f > upper || n == 1) {
f = -1;
return *this;
}
do {
++f;
} while (f <= upper && n % f != 0);
// n is a prime
if (f > upper) {
f = n;
}
while (n % f == 0) {
n /= f;
}
return *this;
}
private:
int f;
int n;
int upper;
};
struct factors {
factors(int n) : n(n) {}
auto begin() const -> factors_iterator { return ++factors_iterator(1, n); }
auto end() const -> factors_iterator { return factors_iterator(); }
private:
int n;
};
void dfs(std::unordered_map<int, std::vector<int>> &graph,
std::vector<bool> &visited, int u) {
visited[u] = true;
for (auto v : graph[u]) {
if (!visited[v]) {
dfs(graph, visited, v);
}
}
}
} // namespace
class Solution {
public:
bool canTraverseAllPairs(const std::vector<int> &nums) {
auto n = nums.size();
std::unordered_map<int, int> gcd;
std::unordered_map<int, std::vector<int>> neighbors;
for (auto i = 0u; i < n; ++i) {
for (auto f : factors(nums[i])) {
if (gcd.contains(f)) {
int u = i;
int v = gcd[f];
neighbors[u].push_back(v);
neighbors[v].push_back(u);
}
gcd[f] = i;
}
}
std::vector<bool> visited(n, false);
dfs(neighbors, visited, 0);
return std::find(visited.begin(), visited.end(), false) ==
visited.end();
}
};
#ifdef _MF_TEST
#include <gtest/gtest.h>
TEST(examples, no_1) {
Solution s;
EXPECT_TRUE(s.canTraverseAllPairs(std::vector{2, 3, 6}));
}
TEST(examples, no_2) {
Solution s;
EXPECT_FALSE(s.canTraverseAllPairs(std::vector{3, 9, 5}));
}
TEST(examples, no_3) {
Solution s;
EXPECT_TRUE(s.canTraverseAllPairs(std::vector{4, 3, 12, 8}));
}
TEST(factors, prime_2) {
std::vector<int> fs;
for (auto f : factors(2)) {
fs.push_back(f);
}
EXPECT_EQ(fs, std::vector{2});
}
TEST(factors, prime_7) {
std::vector<int> fs;
for (auto f : factors(7)) {
fs.push_back(f);
}
EXPECT_EQ(fs, std::vector{7});
}
TEST(factors, prime_29) {
std::vector<int> fs;
for (auto f : factors(29)) {
fs.push_back(f);
}
EXPECT_EQ(fs, std::vector{29});
}
TEST(factors, composite_6) {
std::vector<int> fs;
for (auto f : factors(6)) {
fs.push_back(f);
}
EXPECT_EQ(fs, (std::vector{2, 3}));
}
TEST(factors, composite_15) {
std::vector<int> fs;
for (auto f : factors(15)) {
fs.push_back(f);
}
EXPECT_EQ(fs, (std::vector{3, 5}));
}
TEST(factors, composite_1024) {
std::vector<int> fs;
for (auto f : factors(1024)) {
fs.push_back(f);
}
EXPECT_EQ(fs, std::vector{2});
}
int main(int argc, char **argv) {
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
#endif