947. 移除最多的同行或同列石头(并查集)(傻瓜教程)(python)(LC)

947. 移除最多的同行或同列石头

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] 不能移除,因为它们没有与另一块石头同行/列。

解题:并查集

(对连通分量的理解是并查集的核心之一,事实上,由于刚刚接触并查集算法,我会非常自然的忽略掉连通分量在题目中的作用,导致手足无措的局面)

核心思路:可移除石头个数 = 总个数 - 连通分量的个数
目的:求连通分量

注意事项:

并查集的思想已经很明确,在这里我们只强调几点本题的不同之处)

1.为了区分横纵坐标,我们采用对所有纵坐标做一个变换

可以加上一个参数,例如表长n或者最大表长1000;也可以取负

2.我们要计算连通分量,注意建图时不要出现多余元素

或许是之前遇到的题目都是对一个完整的可迭代对象建图,所以我留下了暴力建图(套用模版)的坏习惯。
在这里,因为石头不是塞满的,而是一个一个给出的,所以我们需要逐步建图的手段。具体体现为类的内置函数add()
又因为暴力建图的.cnt不能使用,所以我们也需要重新定制计算连通分量的手段num_connect_compand()


完整代码

class UnionFind(object):
    def __init__(self):  
        self._father = {
    
    }
        
    def find(self, x):
        root = x 
        while self._father[root] != root:
            root = self._father[root]
        #路径压缩
        while root != x:
            origin_root = self._father[x]
            self._father[x] = root
            x = origin_root
        return root
    
    def add(self, x):
        if x not in self._father:
            self._father[x] = x 

    def merge(self, x, y):
        root_x, root_y = self.find(x), self.find(y)
        if root_x != root_y:
            self._father[root_y] = root_x
            
    def is_connected(self, x, y):
        return self.find(x) == self.find(y)
    
    def num_connect_compand(self):
        return sum(1 for x, fa in self._father.items() if x == fa)

class Solution(object):
    def removeStones(self, stones):
        n = len(stones)
        uf = UnionFind()
        cnt = 0
        for x, y in stones:
            uf.add(x)
            uf.add(y+10000)
            uf.merge(x, y+10000)
        
        return n - uf.num_connect_compand()

猜你喜欢

转载自blog.csdn.net/qq_51174011/article/details/112671625