Beginner Friendly Adjacency List + DFS using unordered sets | C++ | Beats 100%
IntuitionEach row is converted to a set to eliminate duplicates. For all pairs of rows, edges are added if their intersection size meets k. Finally, DFS travers
# Intuition
Each row is converted to a set to eliminate duplicates. For all pairs of rows, edges are added if their intersection size meets `k`. Finally, DFS traverses the graph to count connected components.

# Approach

1. **Preprocessing Rows into Sets:**
   - Convert each row into an `unordered_set` to eliminate duplicate elements within the same row. This ensures that the intersection count between rows is based on distinct values.

2. **Building the Graph:**
   - For each pair of rows (i, j) where `i < j`, compute the intersection size of their sets using a helper function.
   - If the intersection size is ≥ `k`, add an undirected edge between nodes `i` and `j` in an adjacency list (`H`).

3. **DFS for Connected Components:**
   - Initialize a `visited` array to track nodes traversed.
   - For each unvisited node, perform DFS to mark all reachable nodes as visited. Each DFS initiation corresponds to a new connected component.

**Example Walkthrough (k=1):**

- **Rows Converted to Sets:**
  ```
  {1,2}, {1}, {3,4}, {4,5}, {5,6}, {7}
  ```
  
- **Edges Created:**
  - (0-1), (2-3), (3-4) (each pair shares ≥1 element).

- **Connected Components:**
  - Component 1: Nodes 0, 1 (connected via shared '1').
  - Component 2: Nodes 2, 3, 4 (connected via 2-3 and 3-4).
  - Component 3: Node 5 (no edges).
  
**Result:** 3 components.

# Complexity
- Time complexity: $$O(n² * m)$$
<!-- Add your time complexity here, e.g. $$O(n)$$ -->
where `n` is the number of rows and `m` is the average row size.

- Space complexity: $$O(n² + n*m)$$
<!-- Add your space complexity here, e.g. $$O(n)$$ -->
storing adjacency lists for up to O(n²) edges and O(n*m) for row sets.

# Code
```cpp []
class Solution {
public:
    int intersect(unordered_set <int> &a, unordered_set <int> &b){
        int count = 0;
        for(auto &n: b){
            if(a.find(n)!=a.end())count++;
        }
        return count;
    }
    void dfs(int i, vector <bool> &visited, unordered_map <int, vector <int>> &H){
        visited[i] = true;
        for(auto &node: H[i]){
            if(!visited[node])dfs(node, visited, H);
        }
    }
    int numberOfComponents(vector<vector<int>>& properties, int k) {
        int n = properties.size();
        unordered_map <int, vector <int>> H; // Adjacency list for graph
        vector <bool> visited(n, false); // Tracks visited nodes
        vector <unordered_set <int>> p; // Stores each row as a set
        
        // Convert each row to a set to remove duplicates (also reduces time complexity)
        for(auto u: properties){
            unordered_set <int> temp(u.begin(), u.end());
            p.push_back(temp);
        }

        // Build graph
        for(int i=0; i<n; i++){
            for(int j=i+1; j<n; j++){
                if((intersect(p[i], p[j])>=k)){
                    H[i].push_back(j);
                    H[j].push_back(i);
                }
            }
        }
        int res = 0;
        for(int i=0; i<n; i++){
            if(!visited[i]){
                res++;
                dfs(i, visited, H);
            }
        }
        return res;
    }
};
```
['Hash Table', 'Depth-First Search', 'Ordered Set', 'C++']