diff --git a/323/step1.cpp b/323/step1.cpp new file mode 100644 index 0000000..a425064 --- /dev/null +++ b/323/step1.cpp @@ -0,0 +1,50 @@ +/* + +Solve Time : 13:59 + +Time : O(n) +Space : O(n) + +UnionFindを用意する方法をまず思いついたが、UnionFind木を用意する手間が惜しいと考え別ルートへ +UnionFindそのものを用意するのではなく、考え方を流用したコードを考える。 +初期値を-1で初期化したサイズnのベクタを用意する。 +個々の要素に自分のクラスタのリーダーとなるインデックスをもたせる。 +edgesの処理に合わせてそれらを更新していくことでリーダー以外のノードがすべて-1以外の数値を持つようになるので、最後に-1を数える。 +下記に示すケースで間違えたため、それに合わせて修正を加えてパスしたが、エッジケースの想定が甘かった。 +``` +n = 3, edges = [[2,0],[2,1]] +n = 5, edges = [[0,1],[1,2],[0,2],[3,4]] +``` + +修正を加えた結果だいぶUnionFindに近づいた気がする。 +*/ +class Solution { +public: + int countComponents(int n, vector>& edges) { + vector nodes = vector(n, -1); + for (auto edge : edges) { + int left = edge.front(); + int right = edge.back(); + while (nodes[right] >= 0) { + right = nodes[right]; + } + while (nodes[left] >= 0) { + left = nodes[left]; + } + if (left == right) { + continue; + } + if (left > right) { + swap(left, right); + } + nodes[right] = left; + } + int count = 0; + for (auto i : nodes) { + if (i == -1) { + count++; + } + } + return count; + } +}; diff --git a/323/step2_1.cpp b/323/step2_1.cpp new file mode 100644 index 0000000..f5df891 --- /dev/null +++ b/323/step2_1.cpp @@ -0,0 +1,44 @@ +/* +Time : O(n) +Space : O(n) + +step1に対してセルフレビューで修正を加えた +- 各ノードを参照する事に階層を引き上げる処理を加えた。 +- クラスタのトップを表すマジックナンバーを定数化 + +*/ +class Solution { + public: + int countComponents(int n, vector>& edges) { + const int kClusterTop = -1; + vector nodes = vector(n, kClusterTop); + for (auto edge : edges) { + int left = edge.front(); + int right = edge.back(); + while (nodes[right] >= 0) { + const int previous_right = right; + right = nodes[right]; + nodes[previous_right] = right; + } + while (nodes[left] >= 0) { + const int previous_left = left; + left = nodes[left]; + nodes[previous_left] = left; + } + if (left == right) { + continue; + } + if (left > right) { + swap(left, right); + } + nodes[right] = left; + } + int count = 0; + for (auto i : nodes) { + if (i == kClusterTop) { + count++; + } + } + return count; + } +}; diff --git a/323/step2_2.cpp b/323/step2_2.cpp new file mode 100644 index 0000000..b1ff5f7 --- /dev/null +++ b/323/step2_2.cpp @@ -0,0 +1,55 @@ +/* +Time : O(N + M) +Space : O(N + M) + +edges.size() = M + +他の人の解法を参考にDFSを用いて解き直した。 +edge list形式でDFSをするというのが初見でしっくりこなかったが、隣接リスト形式に変換してからDFSするという点はしっくりきた。 +自明にデータ形式を変換する考察が不足しており、素直な解法にたどり着けなかったのでその点を補いたい。 + +*/ +class Solution { + public: + int countComponents(int n, vector>& edges) { + vector> adjacency_nodes = vector>(n, vector()); + vector visited = vector(n, '0'); + for (auto edge : edges) { + const int x = edge.front(); + const int y = edge.back(); + adjacency_nodes[x].push_back(y); + adjacency_nodes[y].push_back(x); + } + int count = 0; + for (int index = 0; index < n; ++index) { + if (visited[index] == '1') { + continue; + } + InvestigateIndexes(index, adjacency_nodes, visited); + ++count; + } + return count; + } + + private: + void InvestigateIndexes(int start_index, + const vector>& adjacency_nodes, + vector& visited) { + stack next_indexes; + next_indexes.emplace(start_index); + while (!next_indexes.empty()) { + const int index = next_indexes.top(); + next_indexes.pop(); + if (visited[index] == '1') { + continue; + } + visited[index] = '1'; + for (int adjcent_index : adjacency_nodes[index]) { + if (visited[adjcent_index] == '1') { + continue; + } + next_indexes.emplace(adjcent_index); + } + } + } +}; diff --git a/323/step3.cpp b/323/step3.cpp new file mode 100644 index 0000000..e71d1f2 --- /dev/null +++ b/323/step3.cpp @@ -0,0 +1,39 @@ +class Solution { + public: + int countComponents(int n, vector>& edges) { + vector> adjcent_indexes = vector>(n, vector()); + for (auto edge : edges) { + const int left = edge.front(); + const int right = edge.back(); + adjcent_indexes[left].emplace_back(right); + adjcent_indexes[right].emplace_back(left); + } + set visited; + int count = 0; + for (int index = 0; index < n; ++index) { + if (visited.contains(index)) { + continue; + } + ++count; + VisitCluster(index, adjcent_indexes, visited); + } + return count; + } + + private: + void VisitCluster(const int start_index, const vector>& adjacent_indexes, set& visited) { + stack next_indexes; + next_indexes.emplace(start_index); + while (!next_indexes.empty()) { + const int index = next_indexes.top(); + next_indexes.pop(); + if (visited.contains(index)) { + continue; + } + visited.insert(index); + for (const int next_index : adjacent_indexes[index]) { + next_indexes.emplace(next_index); + } + } + } +};