编程-并查集
初始时,有 N 个朋友圈,即每个人一个圈子。
如果两个人是朋友,则进行一次 merge,如果merge成功,则朋友圈数量减一。
std::vector<int> fa; void init(int N) { fa.resize(N); for (int i = 0; i < N; i++) { fa[i] = i; } } int find(int x) { int r = x; while(fa[r] != r) { r = fa[r]; } while(fa[x] != x) { int t = fa[x]; fa[x] = r; x = t; } return x; } bool merge(int u, int v) { int ru = find(u); int rv = find(v); if (ru == rv) { return false; } fa[ru] = rv; return true; } class Solution { public: int findCircleNum(vector<vector<int>>& M) { int N = M.size(); init(N); int anw = N; for (int i = 0; i < N; i++) { for (int j = i+1; j < N; j++) { if (M[i][j] && merge(i, j)) { anw --; } } } return anw; } };
本文将呈现如下内容:
- 一个在实际工作中遇到的问题
- 用 C++ 实现一个并查集
- 路径压缩
547. 省份数量
有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
返回矩阵中 省份 的数量。
示例 1:
输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2
示例 2:
输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出:3
提示:
1 <= n <= 200
n == isConnected.length
n == isConnected[i].length
isConnected[i][j] 为 1 或 0
isConnected[i][i] == 1
isConnected[i][j] == isConnected[j][i]
class Solution { public: vector<int> p; // 路径压缩 int find(int x){ if(p[x] != x) p[x] = find(p[x]); return p[x]; } int findCircleNum(vector<vector<int>>& isConnected) { int n = isConnected.size(); // 初始化 for(int i = 0; i < n; i ++) p.push_back(i); int cnt = n; for(int i = 0; i < n; i ++) for(int j =0; j < i; j++) if(isConnected[i][j] && find(i) != find(j)){ p[find(i)] = find(j); // 集合合并 cnt --; } return cnt; } };
200. 岛屿数量
给你一个由
'1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例 1:
输入:grid = [ ["1","1","1","1","0"], ["1","1","0","1","0"], ["1","1","0","0","0"], ["0","0","0","0","0"] ] 输出:1
示例 2:
输入:grid = [ ["1","1","0","0","0"], ["1","1","0","0","0"], ["0","0","1","0","0"], ["0","0","0","1","1"] ] 输出:3
提示:
m == grid.lengthn == grid[i].length1 <= m, n <= 300grid[i][j]的值为'0'或'1'
class UF { public: vector<int> parent; int n; UF(int _n) : n(_n), parent(_n) { iota(parent.begin(),parent.end(),0); } int find(int x) { return x == parent[x] ? x : parent[x] = find(parent[x]); } void merge(int x, int y) { x = find(x); y = find(y); if(x == y) return; parent[x] = y; n--; } bool isConnected(int x, int y) { return find(x) == find(y); } int getSize() { return n; } }; class Solution { public: int dx[4] = {-1,1,0,0}; int dy[4] = {0,0,-1,1}; int numIslands(vector<vector<char>>& grid) { int m = grid.size(); int n = m == 0 ? 0 : grid[0].size(); if(m == 0 || n == 0) return 0; vector<int> cnt(2,0); for(int i=0;i<m;i++) for(int j=0;j<n;j++) cnt[grid[i][j]-'0']++; // (i,j) -> index = i*n + j UF uf(m*n); for(int i=0;i<m;i++) { for(int j=0;j<n;j++) { if(grid[i][j] == '0') continue; for(int k=0;k<4;k++) { int xx = i+dx[k], yy = j+dy[k]; if(xx < 0 || xx >= m || yy < 0 || yy >= n) continue; if(grid[xx][yy] == '1') uf.merge(i*n+j, xx*n+yy); } } } return uf.getSize() - cnt[0]; } };
const int N = 100010; class Solution { public: int p[N]; int find(int x) { if(p[x] != x) p[x] = find(p[x]); return p[x]; } int numIslands(vector<vector<char>>& grid) { int m = grid.size(), n = grid[0].size(); for(int i = 0; i < m; i ++) { for(int j = 0; j < n; j ++) { p[i * n + j] = i * n + j; } } int res = 0; int dx[4] = {-1, 0 , 1, 0}, dy[4] = {0, -1, 0, 1}; for(int i = 0; i < m * n; i ++) { int prex = i / n, prey = i % n; if(grid[prex][prey] == '1') { res ++; for(int j = 0; j < 4; j ++) { int ux = prex + dx[j], uy = prey + dy[j]; if(ux >= 0 && ux < m && uy >= 0 && uy < n && grid[ux][uy] == '1') { int u = ux * n + uy; int pi = find(i), pu = find(u); if(pi != pu) { p[pu] = pi; res --; } } } } } return res; } };

浙公网安备 33010602011771号