我们将石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。
每次 move 操作都会移除一块所在行或者列上有其他石头存在的石头。
请你设计一个算法,计算最多能执行多少次 move 操作?
示例 1:
输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
输出:5
示例 2:
输入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
输出:3
示例 3:
输入:stones = [[0,0]]
输出:0
提示:
1 <= stones.length <= 1000
0 <= stones[i][j] < 10000
/**
* 每一个坐标点上的石头可以覆盖一个十字区域就是它所在的行和列。这个石头没被移除,那么在“此行此列”的其他石头就都可以全部移除。
* 把可以建立起行列关系的石头,放在同一个集合里,记录最后可以形成的集合的个数。用stones的个数减去集合数量就是可以move的最大次数。集合的元素不一定全部是同行同列的。
* 注意:并查集的核心思想是用一个点来表示一个集合,在进行行列连接的时候,由于行和列的取值范围是一样的,防止覆盖,将列值映射到 pre数组的右边。这样就可以把行、列相关的集合只有一个点表示。
*/
class Solution {
int[] pre = new int[10000+10000];
public int removeStones(int[][] stones) {
//初始化
for (int i=0;i<pre.length;++i){
pre[i]=i;
}
//
for (int i=0;i<stones.length;++i){
union(stones[i][0],stones[i][1]+10000);
}
Set<Integer> set = new HashSet<>();
for (int i =0;i<stones.length;++i){
set.add(find(stones[i][0]));
}
return stones.length-set.size();
}
private void union(int a, int b) {
int x = find(a);
int y = find(b);
if (x!=y){
pre[x] = y;
}
}
private int find(int a) {
if (a!=pre[a]){
a=pre[a];
}
return a;
}
}