Showing posts with label Union Find. Show all posts
Showing posts with label Union Find. Show all posts

Wednesday, April 19, 2017

Number of Connected Components in an Undirected Graph -- LeetCode 323

[Question]
Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to find the number of connected components in an undirected graph.
Example 1:
     0          3
     |          |
     1 --- 2    4
Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], return 2.
Example 2:
     0           4
     |           |
     1 --- 2 --- 3
Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [3, 4]], return 1.
Note:
You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

[Analysis]
Classic Union-find problem.

[Solution]
class UnionFind {
    vector<int> u;

public:
    UnionFind(int n) {
        u =vector<int>(n,0);
        for (int i=0; i<n; i++)
            u[i] = i;
    }

    int find(int i) {
        if (u[i]==i) return i;
        u[i] = find(u[i]);
        return u[i];
    }

    void unions(int i, int j) {
        u[find(i)] = find(j);
    }
};

int countComponents(vector<pair<int,int>>& edges, int n) {
    UnionFind uf(n);
   
    for (auto& e:edges)
        uf.unions(e.first, e.second);
   
    unordered_set<int> res;
    for(int i=0; i<n; i++)
        res.insert(uf.find(i));

    return res.size();
}


Wednesday, November 16, 2016

Number of Islands -- LeetCode 200

[Question]
Given a 2d grid map of '1's (land) and '0's (water), count the number of islands. An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
11110
11010
11000
00000
Answer: 1
Example 2:
11000
11000
00100
00011
Answer: 3
[Analysis]
Scanning through each position in the grid, if there is an '1', use BFS and find all '1' in this island. Then find another '1' for another island. The time complexity is O(MxN). 
Using DFS is also good and easier to implement. 
[Solution]
//
//--- BFS ---
//
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        if (grid.empty()) return 0;
        
        int m=grid.size(), n=grid[0].size();
        int count=0;
        
        auto expand=[&grid, m, n](int x, int y) {
            queue<pair<int,int>> que;
            vector<pair<int,int>> dir = {{0,1}, {1,0},{0,-1},{-1,0}};
            
            que.push({x,y}); grid[x][y]=0;
            while (!que.empty()) {
                auto loc = que.front();
                que.pop();
                
                for (auto d: dir) {
                    int nx=loc.first+d.first, ny=loc.second+d.second;
                    if (nx>=0 &&nx<m && ny>=0 && ny<n && grid[nx][ny]=='1') {
                        que.push({nx,ny}); grid[nx][ny]=0;
                    }
                }
            }
        };
        
        for (int i=0; i<m; i++) 
            for (int j=0; j<n; j++) {
                if (grid[i][j]=='1') {
                    expand(i, j);
                    count++;
                }
            }
        return count;
    }
};

//
//--- DFS ---
//
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) {
        if (grid.empty()) return 0;
        
        int m=grid.size(), n=grid[0].size();
        function<int(int,int)> dfs = [&] (int i, int j) {
            if (i<0||i>=m||j<0 || j>=n || grid[i][j]=='0') return 0;
            grid[i][j]='0';
            dfs(i+1,j); dfs(i-1,j); dfs(i,j+1); dfs(i,j-1);
            return 1;
        };
        
        int count=0;
        for(int i=0; i<m; i++) 
            for (int j=0; j<n; j++)
                count+= dfs(i, j);
                
        return count;
    }
};

Tuesday, June 4, 2013

Longest Consecutive Sequence

[Question]
Given an unsorted array of integers, find the length of the longest consecutive elements sequence.
For example,
Given [100, 4, 200, 1, 3, 2],
The longest consecutive elements sequence is [1, 2, 3, 4]. Return its length: 4.
Your algorithm should run in O(n) complexity.
[Analysis]
Each element is a consecutive sequence of length 1. Suppose element A, it can be represented as a sequence [A, A+1). If A+1 is in the array, the sequence that starts from A can be represented as [A, A+2). Repeat the finding process, using a hash table which maps A (the starting value) to the ending value (exclusive) of the sequence.

It is equivalent to use mapping between A and "length of consecutive sequence", as shown in 2nd solution code.

[Solution]
class Solution {
public:
    int longestConsecutive(vector<int> &num) {
        if (num.size()<2) return num.size();
     
        int max_len = 1;
        unordered_map<int,int> map;    
        for (auto a: num)
            map[a] = a+1;

        for(auto kv: map) {
            int a = kv.first;
            int next = map[a];
            while (map.find(next)!=map.end()) {
                map[a] = map[next];
                map.erase(next);
                next = map[a];
            }
            max_len = max(map[a]-a, max_len);
        }

        return max_len;
    }
};

//Solution 2nd
class Solution {
public:
    int longestConsecutive(vector<int> &num) {
        if (num.empty()) return 0;
        int max_len = 1;
   
        unordered_map<int,int> map;  
        for (auto& a: num) map[a] = 1;

        for(auto& kv: map) {
            int a = kv.first;
            int next=a+map[a];
            while (map.count(next)) {
                map[a] += map[next];
                map.erase(next);
                next=a+map[a];
            }
            max_len = max(max_len, map[a]);
        }

        return max_len;
    }
};