并查集模板 扁平化+小挂大
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
| public static int MAXN = 1000001;
public static int[] father = new int[MAXN];
public static int[] size = new int[MAXN];
public static int[] stack = new int[MAXN];
public static int n;
public static void build() { for (int i = 0; i <= n; i++) { father[i] = i; size[i] = 1; } }
public static int find(int i) { int size = 0; while (i != father[i]) { stack[size++] = i; i = father[i]; } while (size > 0) { father[stack[--size]] = i; } return i; }
public static boolean isSameSet(int x, int y) { return find(x) == find(y); }
public static void union(int x, int y) { int fx = find(x); int fy = find(y); if (fx != fy) { if (size[fx] >= size[fy]) { size[fx] += size[fy]; father[fy] = fx; } else { size[fy] += size[fx]; father[fx] = fy; } } }
|
模板2 只有扁平化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public static int MAXN = 200001;
public static int[] father = new int[MAXN];
public static int n;
public static void build() { for (int i = 0; i <= n; i++) { father[i] = i; } }
public static int find(int i) { if (i != father[i]) { father[i] = find(father[i]); } return father[i]; }
public static boolean isSameSet(int x, int y) { return find(x) == find(y); }
public static void union(int x, int y) { father[find(x)] = find(y); }
|
情侣牵手
leetcode 765
思路:把编号i,i+1的情侣看出编号为i/2的情侣对.按顺序每次让两个人的情侣编号两两进行合并,如果是一对情侣(情侣编号一样)那么集合个数不会变,如果不是比如第一个人属于第3对,第二个人属于第5对,那么把3,5合成一个集合。最后原始的情侣对数减去剩下的集合个数就是答案。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| public static final int MAX = 31;
public static int[] father = new int[MAX];
public static void build(int m){ for(int i =0;i<m;i++){ father[i] = i; } }
public static int find(int i) { if (i != father[i]) { father[i] = find(father[i]); } return father[i]; }
public static void union(int x,int y){ int fx = find(x); int fy = find(y); if(fx!=fy){ father[fx] = fy; cnts--; } }
public static int cnts; public int minSwapsCouples(int[] row) { int n =row.length; cnts = n/2; build(n/2); for(int i =0;i<n;i+=2){ union(row[i]/2,row[i+1]/2); } return n/2 - cnts; }
|
相似字符串组
leetcode 839
思路:两层for循环每次判断两个字符串是否相似,相似的话就合并两个字符串的集合。最后返回集合个数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| public static int MAXN = 301;
public static int[] father = new int[MAXN];
public static int sets;
public static void build(int n) { for (int i = 0; i < n; i++) { father[i] = i; } sets = n; }
public static int find(int i) { if (i != father[i]) { father[i] = find(father[i]); } return father[i]; }
public static void union(int x, int y) { int fx = find(x); int fy = find(y); if (fx != fy) { father[fx] = fy; sets--; } }
public static int numSimilarGroups(String[] strs) { int n = strs.length; int m = strs[0].length(); build(n); for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { if (find(i) != find(j)) { int diff = 0; for (int k = 0; k < m && diff < 3; k++) { if (strs[i].charAt(k) != strs[j].charAt(k)) { diff++; } } if (diff == 0 || diff == 2) { union(i, j); } } } } return sets; }
|
岛屿数量
leetcode 200
思路:其实这道题最优解是洪水填充,但是这里用并查集也可以做。把二维下标转为一维编号 i*n+j。然后依次遍历,如果自己是1 的话就 查看 右边 跟 下边是不是1,如果是的话就合并。最后返回集合个数即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| public static void build(char[][] grid,int m,int n){ cnts = 0; for(int i =0;i<m;i++){ for(int j =0;j<n;j++){ if(grid[i][j] == '1'){ father[i*n+j] = i*n+j; cnts++; } } } }
public static int find(int i){ if(i != father[i]){ father[i] = find(father[i]); } return father[i]; }
public static void union(int x,int y){ int fx = find(x); int fy = find(y); if(fx!=fy){ father[fx] = fy; cnts--; } }
public int numIslands(char[][] grid) { int m = grid.length; int n = grid[0].length; build(grid,m,n); for(int i =0;i<m;i++){ for(int j =0;j<n;j++){ if(grid[i][j] == '1'){ if( i!=m-1 && grid[i+1][j] == '1'){ union(i*n+j,(i+1)*n+j); } if( j!=n-1 && grid[i][j+1]=='1'){ union(i*n+j,i*n+j+1); } } } } return cnts; }
|
专家开会
leetcode 2092
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| public static int MAXN = 100001;
public static int[] father = new int[MAXN];
public static boolean[] secret = new boolean[MAXN];
public static void build(int n, int first) { for (int i = 0; i < n; i++) { father[i] = i; secret[i] = false; } father[first] = 0; secret[0] = true; }
public static int find(int i) { if (i != father[i]) { father[i] = find(father[i]); } return father[i]; }
public static void union(int x, int y) { int fx = find(x); int fy = find(y); if (fx != fy) { father[fx] = fy; secret[fy] |= secret[fx]; } }
public static List<Integer> findAllPeople(int n, int[][] meetings, int first) { build(n, first); Arrays.sort(meetings, (a, b) -> a[2] - b[2]); int m = meetings.length; for (int l = 0, r; l < m;) { r = l; while (r + 1 < m && meetings[l][2] == meetings[r + 1][2]) { r++; } for (int i = l; i <= r; i++) { union(meetings[i][0], meetings[i][1]); } for (int i = l, a, b; i <= r; i++) { a = meetings[i][0]; b = meetings[i][1]; if (!secret[find(a)]) { father[a] = a; } if (!secret[find(b)]) { father[b] = b; } } l = r + 1; } List<Integer> ans = new ArrayList<>(); for (int i = 0; i < n; i++) { if (secret[find(i)]) { ans.add(i); } } return ans; }
|