这道题我一看类似矩阵的,我就知道要用到并查集,并查集还那样会写的会写,不理解的还是不理解.而且主体思路有一点儿,上一题的灵感,尝试了一下不太对,所以看助教的讲解,需要判读.然后主题思路如果按照上一题89题的考虑,但是并查集就要换个样,具体看方法二
方法一
计数是从最大的n开始
/**
* @param {number[][]} stones
* @return {number}
*/
var removeStones = function(stones) {
const uf = new UnionFind(stones.length);
for (let i=0;i<stones.length; i++) {
for (let j=0;j<stones.length; j++) {
const [x1,x2] = stones[i];
const [y1,y2] = stones[j];
if(x1 === y1 || x2 === y2){
uf.unite(i,j)
}
}
}
// 原有的石头数量 - 合并完以后剩下的石头数量 就是移除的石头数量
return stones.length - uf.getCount() ;
};
class UnionFind {
constructor(n) {
this.parent = new Array(n).fill(0).map((v, i) => i);
this.size = new Array(n).fill(1);
this.count = n;
}
find(index) {
let root = this.parent[index];
if (root != index) {
root = this.find(root)
}
return root
}
unite(index1, index2) {
let root1 = this.find(index1), root2 = this.find(index2)
if (root1 === root2) {
return;
}
if (root1 < root2) {
[root1, root2] = [root2, root1]
}
this.parent[root2] = root1;
this.size[root1] += this.size[root2];
this.count--;
}
getCount() {
return this.count;
}
connected(index1, index2) {
return this.find(index1) === this.find(index2)
}
}
方法二
计数count从0开始
/**
* @param {number[][]} stones
* @return {number}
*/
var removeStones = function(stones) {
// 思路,可移除个数=石头总数-连通量的个数
// union-find来算连通量
// 对于每个stone,我们连接union它的行和列。因为,比如一个stone[i,j]的存在,它连通了i行和j列;又一个stone[k,j]存在,它连通了k行和j列
// 这样的话,k行与i行就是通过j列连通的
// 一个连通量的根节点可以是某一行或某一列
// 注意,对于每一列的处理我们要+10000,这样就不会和行重复了
const unionFindSet = new UnionFind();
for(let stone of stones) {
unionFindSet.union(stone[0], stone[1] + 10000);
}
return stones.length - unionFindSet.getCount();
};
class UnionFind {
constructor() {
this.parents = [];
this.ranks = [];
this.count = 0;
}
init(x) {
if(this.parents[x] === undefined) {
this.parents[x] = x;
this.ranks[x] = 0;
this.count++;
}
}
find(x) {
if(this.parents[x] !== x) {
this.parents[x] = this.find(this.parents[x]);
}
return this.parents[x];
}
union(x, y) {
this.init(x); this.init(y);
let rootX = this.find(x), rootY = this.find(y);
if(rootX === rootY) return;
if(this.ranks[rootX] > this.ranks[rootY]) {
this.parents[rootY] = rootX;
} else if(this.ranks[rootX] < this.ranks[rootY]) {
this.parents[rootX] = rootY;
} else {
this.parents[rootY] = rootX;
this.ranks[rootX]++;
}
this.count--;
}
getCount() {
return this.count;
}
}