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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Grayson Zhang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值