/** * n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。 给你一个长度为 n 的数组 stones ,其中 stones[i] = [xi, yi] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。 */ //思路,并查集 public class test947 { //输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]] 5 public static void main(String[] args) { int [][]stones={{0,0},{0,1},{1,0},{1,2},{2,1},{2,2}}; int x=removeStones(stones); } public static int removeStones(int[][] stones) { if(stones.length==1){ return 0; } int n=stones.length; int []parents=new int[stones.length]; for(int i=0;i<n;i++){ parents[i]=i; } int res=n; for(int i=0;i<n-1;i++){ for(int j=i+1;j<n;j++){ int a=find(parents, i); int b=find(parents, j); if(stones[i][0]==stones[j][0]||stones[i][1]==stones[j][1]){ if(a!=b){ parents[a]=b; res--; } } } } return n-res; } public static int find(int []parent,int i){ if(parent[i]!=i){ parent[i]=find(parent,parent[i]); } return parent[i]; } }
对于并查集,一般的模板是这样
// 未改进版本 class Djset { public: vector<int> parent; // 记录节点的根 Djset(int n): parent(vector<int>(n)) { for (int i = 0; i < n; i++) parent[i] = i; } int find(int x) { if (x != parent[x]) return find(parent[x]); return parent[x]; } void merge(int x, int y) { int rootx = find(x); int rooty = find(y);
//这个merge的地方写merge逻辑,例如对于移出同行同列石头,就是如果行或者列相同,如果a!=b,也就是之前没合并,则合并,每次合并剩下的并查集个数-1
//对于字符串交换排序,直接merge之后,遍历所有元素,将key取出来做 map的key,value用排序队列,每次拿出来每个key的从小到大
//对于树的冗余连接,每根边的两个端点都判断是不是在同一并查集,不是就放在一起,是就直接return
parent[rooty] = rootx; } };
要特别注意维护的parent里面是索引下标