移除最多的同行或同列石头
题目介绍
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] 不能移除,因为它没有与另一块石头同行/列。
示例 2:
输入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
输出:3
解释:一种移除 3 块石头的方法如下所示:
1. 移除石头 [2,2] ,因为它和 [2,0] 同行。
2. 移除石头 [2,0] ,因为它和 [0,0] 同列。
3. 移除石头 [0,2] ,因为它和 [0,0] 同行。
石头 [0,0] 和 [1,1] 不能移除,因为它们没有与另一块石头同行/列。
示例 3:
输入:stones = [[0,0]]
输出:0
解释:[0,0] 是平面上唯一一块石头,所以不可以移除它。
提示:
1 <= stones.length <= 1000
0 <= xi, yi <= 104
不会有两块石头放在同一个坐标点上
思路分析
题意分析
自己陷入过的误区
能够连通的只需要保留一个,我首先想到的是深度或者广度遍历,从一个点出发,遍历这个点能触及到的所有点,感觉也非常合理
但是该题的陷阱也在于此,题目对于stones.length,仅限制在1-1000中,而横纵坐标却在10000范围内,如果我们构建一个图,需要的是10000*10000的内存,对于仅仅不到1000的数据,也太稀疏了
如果不使用矩阵,深度或者广度遍历也很困难,难道构建两层for(int i=0;i<10000;i++)这样去遍历吗。获取我们可以采用邻接矩阵
思路一 广度优先遍历
最后我的思路是这样的
其中横坐标纵坐标链表的实现可以使用HashMap<Interger,HashSet< Interger >>进行,其中的set随着不断的访问还能进行删除,减少重复访问
思路二 并查集
这个就很符合题意了,创建一个一维数组存放各个石头的父亲节点
然后考虑三种情况 创建两个HashMap分别存储行对应的点和列对应的点
- 该石头的行列都没有出现过,那么是新石头,自己创建一个家族
- 该石头的行出现过,那把此列指像自己,然后通过行找到那个点,并通过getFather找到最终节点,把自己并上去
- 如果该石头的行列都出现,同2先查到行列所属的最终节点是不是一个,是一个那就没事了,如果不是一个就合并两大家族
class Solution {
int[] father;
public int removeStones(int[][] stones) {
father=new int[stones.length];
for (int i = 0; i < father.length; i++) {
father[i]=-1;
}
HashMap<Integer,Integer>row=new HashMap<>();
HashMap<Integer,Integer>line=new HashMap<>();
for (int i = 0; i < stones.length; i++) {
if(row.containsKey(stones[i][0])&&line.containsKey(stones[i][1])){
int num1=getFather(row.get(stones[i][0]));
int num2=getFather(line.get(stones[i][1]));
if(num1!=num2){
father[num1]=num2;
}
father[i]=num2;
}else if(row.containsKey(stones[i][0])){
int num1=getFather(row.get(stones[i][0]));
father[i]=num1;
line.put(stones[i][1],i);
}else if(line.containsKey(stones[i][1])){
int num2=getFather(line.get(stones[i][1]));
father[i]=num2;
row.put(stones[i][0],i);
}else {
row.put(stones[i][0],i);
line.put(stones[i][1],i);
}
}
int count=0;
//System.out.println(Arrays.toString(father));
//System.out.println(row);
//System.out.println(line);
for (int i = 0; i < father.length; i++) {
if(father[i]!=-1)count++;
}
return count;
}
public int getFather(Integer num){
if(father[num]==-1)return num;
return getFather(father[num]);
}
}