package com.heu.wsq.leetcode.bingchaji;
import java.util.HashMap;
import java.util.Map;
/**
* 947. 移除最多的同行或同列石头
* @author wsq
* @date 2021/1/15
* n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。
* 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。
* 给你一个长度为 n 的数组 stones ,其中 stones[i] = [xi, yi] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。
*
* 示例 1:
* 输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
* 输出:5
* 解释:一种移除 5 块石头的方法如下所示:
* 1. 移除石头 [2,2] ,因为它和 [2,1] 同行。
* 2. 移除石头 [2,1] ,因为它和 [0,1] 同列。
* 3. 移除石头 [1,2] ,因为它和 [1,0] 同行。
* 4. 移除石头 [1,0] ,因为它和 [0,0] 同列。
* 5. 移除石头 [0,1] ,因为它和 [0,0] 同行。
* 石头 [0,0] 不能移除,因为它没有与另一块石头同行/列。
*
* 链接:https://leetcode-cn.com/problems/most-stones-removed-with-same-row-or-column
*/
public class RemoveStones {
/**
* 计算出由石头坐标构成的图的连通分量是多少,然后石头的总数减去连通分量数目,就是能去除最多石头的数量
*/
public int removeStones(int[][] stones){
int n = stones.length;
if (n == 0){
return 0;
}
UnionFind unionFind = new UnionFind();
for (int[] stone: stones){
unionFind.union(stone[0] + 10000, stone[1]);
}
return n - unionFind.getCount();
}
private class UnionFind{
private Map<Integer, Integer> parent;
private int count;
public UnionFind(){
this.parent = new HashMap<>();
this.count = 0;
}
private int find(int x){
if (!parent.containsKey(x)){
parent.put(x, x);
count++;
}
int r = x;
while (r != this.parent.get(r)){
r = this.parent.get(r);
}
int k = x;
while (k != r){
int tmp = this.parent.get(k);
this.parent.put(k, r);
k = tmp;
}
return r;
}
private void union(int x, int y){
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY){
return;
}
this.parent.put(rootX, rootY);
count--;
}
public int getCount(){
return this.count;
}
}
}