Skip to content

Conversation

@ErdemT09
Copy link
Collaborator

@ErdemT09 ErdemT09 commented May 12, 2021

Issue.
There are 2 solutions for this question, similar to this, a Union-Find approach, and a DFS approach.

Approach 1: DFS:
This is a graph question and the graph is pretty easy to construct in this question. For this, we can use a list of lists as a graph, where we add both corners of an edge to their respective lists in the graph, as it should be undirected.
After that, we can just search through each node and their neighbors using DFS. We mark all nodes we encounter as visited, so we don't DFS them or their neighbors again. While looping through our graph list, if we can encounter a non-visited node, that means that there is an unvisited "connected component" here. We increment our counter according to this.
In this image, for example:
image
We begin iterating from loop 0 and DFS this node as it is not visited.
In DFS, we mark it visited.
From its neighbors, we first visit 1 and mark it visited. 0 is a neighbor of 1, but we return back when we visit it because it is already visited. From 1's neighbors, we first visit 2 and mark it visited. At 2, We return back when we visit 0 and 1 again.
Then we DFS to 1's other neighbor 8 and to 5 from there. Same visited checks also happen here.
While iterating through the graph, when try to DFS the node 2 for example, the procedure will immediately return as 2 is marked visited.
The same DFS will also take place by 3 and 4. We can check if our DFS is successful by assigning it a integer value of 0 and 1.

Approach 2: Union-find:
It is important to understand that:
If a new given edge connects 2 previously discrete nodes, then the number of connected components decreases.
If we have [0,1] and [2,3], we have 4 nodes, and 2 edges reduces the number of connected components to 2.
If we connect 2 and 1 for example, the number will reduce to 1.
We can check in which component a node is by storing its root node somewhere. Until a node is in its own root, we have to search recursively through a node's root, in order to find the main root. And set one's root to be the another.
At the end, we return our reduced number of nodes as to be seen in the code.

@ErdemT09
Copy link
Collaborator Author

Approach 3: BFS:
We just do the same that we had done with DFS, but we visit nodes layer by layer, avoiding recursion.

boolean[] visited;
List<List<Integer>> connections = new ArrayList<>();

public int countComponents(int[][] edges, int n) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice solution.
Can we alter the params order:
public int countComponents(int n, int[][] edges)

image

Comment on lines 30 to 36
private int findRoot(int key) {
if (key == roots[key])
{
return key;
}
return findRoot(roots[key]);
}
Copy link
Collaborator

@altay9 altay9 May 12, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we use "path compression" it will take 1ms; otherwise, it takes 4ms.

private int findRoot(int key) {
        if (key != roots[key])
        {
            roots[key] = roots[roots[key]];
            key = roots[key];
            return findRoot(key);
        }else{
            return key;
        }
    }


int roots[];

public int countComponents(int[][] edges, int n) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we alter the params order:
public int countComponents(int n, int[][] edges)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All fixed.

Copy link
Collaborator

@altay9 altay9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All approved.
Thanks for these nice solutions and drawing.

@ErdemT09
Copy link
Collaborator Author

ErdemT09 commented May 12, 2021

How does the BFS solution perform on LeetCode? It shouldn't be different from DFS though.

@ErdemT09 ErdemT09 linked an issue May 13, 2021 that may be closed by this pull request
@altay9
Copy link
Collaborator

altay9 commented May 13, 2021

How does the BFS solution perform on LeetCode? It shouldn't be different from DFS though.

Yes. It is fine enough with 4ms.

@ErdemT09 ErdemT09 merged commit 6345fb7 into master May 13, 2021
@ErdemT09 ErdemT09 deleted the 323.-Number-of-Connected-Components-in-an-Undirected-Graph branch May 13, 2021 15:40
@altay9 altay9 mentioned this pull request Jun 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

323. Number of Connected Components in an Undirected Graph

3 participants