-
Notifications
You must be signed in to change notification settings - Fork 0
323. Number of Connected Components in an Undirected Graph #33
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<vector<int>>& edges) { | ||
vector<int> nodes = vector<int>(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; | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/* | ||
Time : O(n) | ||
Space : O(n) | ||
|
||
step1に対してセルフレビューで修正を加えた | ||
- 各ノードを参照する事に階層を引き上げる処理を加えた。 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://discord.com/channels/1084280443945353267/1183683738635346001/1197738650998415500 |
||
- クラスタのトップを表すマジックナンバーを定数化 | ||
|
||
*/ | ||
class Solution { | ||
public: | ||
int countComponents(int n, vector<vector<int>>& edges) { | ||
const int kClusterTop = -1; | ||
vector<int> nodes = vector<int>(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; | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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<vector<int>>& edges) { | ||
vector<vector<int>> adjacency_nodes = vector<vector<int>>(n, vector<int>()); | ||
vector<char> visited = vector<char>(n, '0'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 個人的には、0, 1 を使いたいです。'1' ではなくて。 |
||
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<vector<int>>& adjacency_nodes, | ||
vector<char>& visited) { | ||
stack<int> 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); | ||
} | ||
} | ||
} | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
class Solution { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. とても良いと思います。 |
||
public: | ||
int countComponents(int n, vector<vector<int>>& edges) { | ||
vector<vector<int>> adjcent_indexes = vector<vector<int>>(n, vector<int>()); | ||
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<int> 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<vector<int>>& adjacent_indexes, set<int>& visited) { | ||
stack<int> 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); | ||
} | ||
} | ||
} | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ほとんど Union Find ですが、ここのところで、nodes のグラフの単純化が行われていないので、結果的に計算時間はかかるかもしれませんね。ここで、元の edge.front(), edge.back() から上流の node に対して、nodes[node] = left にすれば、Union Find を展開したものになっていると思います。