js(90)~947. 移除最多的同行或同列石头-并查集

101 阅读1分钟

力扣本题传送门

image.png

这道题我一看类似矩阵的,我就知道要用到并查集,并查集还那样会写的会写,不理解的还是不理解.而且主体思路有一点儿,上一题的灵感,尝试了一下不太对,所以看助教的讲解,需要判读.然后主题思路如果按照上一题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;
    }
}