LeetCode 947. Most Stones Removed with Same Row or Column - 彻底掌握并查集(Union Find)系列题20

该博客介绍了如何通过并查集数据结构解决一个算法问题:在一个二维平面上,移除最多数量的石头。每颗石头位于整数坐标上,当两颗石头在同一行或同一列时,可以移除其中一颗。给出所有石头的位置,目标是找出能移除的最大石头数。博客中提供了详细的解决方案和代码实现,展示了如何利用并查集高效地找到不同集合,并计算可以移除的石头数量。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

On a 2D plane, we place n stones at some integer coordinate points. Each coordinate point may have at most one stone.

A stone can be removed if it shares either the same row or the same column as another stone that has not been removed.

Given an array stones of length n where stones[i] = [xi, yi] represents the location of the ith stone, return the largest possible number of stones that can be removed.

Example 1:

Input: stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
Output: 5
Explanation: One way to remove 5 stones is as follows:
1. Remove stone [2,2] because it shares the same row as [2,1].
2. Remove stone [2,1] because it shares the same column as [0,1].
3. Remove stone [1,2] because it shares the same row as [1,0].
4. Remove stone [1,0] because it shares the same column as [0,0].
5. Remove stone [0,1] because it shares the same row as [0,0].
Stone [0,0] cannot be removed since it does not share a row/column with another stone still on the plane.

Example 2:

Input: stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
Output: 3
Explanation: One way to make 3 moves is as follows:
1. Remove stone [2,2] because it shares the same row as [2,0].
2. Remove stone [2,0] because it shares the same column as [0,0].
3. Remove stone [0,2] because it shares the same row as [0,0].
Stones [0,0] and [1,1] cannot be removed since they do not share a row/column with another stone still on the plane.

Example 3:

Input: stones = [[0,0]]
Output: 0
Explanation: [0,0] is the only stone on the plane, so you cannot remove it.

Constraints:

  • 1 <= stones.length <= 1000
  • 0 <= xi, yi <= 104
  • No two stones are at the same coordinate point.

题目要我们尽可能多地从一个二维矩阵里移除石头,给的移除条件是,如果一颗石头所在的行或者列上有其他石头那么这颗石头就可以被移除。因此如果我们把具有相同行坐标或者相同列坐标的石头合并成一个集合,那么这个集合里石头就可以一颗一颗地被移除直到只剩下最后一颗。也就说最后每个集合都只剩下一颗石头,因此石头总数减去集合个数就是最多可移除的石头数。很显然这种问题用并查集UnionFind解答再适合不过。

class UnionFind:
    def __init__(self, n):
        self.parent = list(range(n))
        self.size = [1] * n
        self.cnt = n
        
    def find(self, x):
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def merge(self, x, y):
        px, py = self.find(x), self.find(y)
        if px == py:
            return
        if self.size[px] > self.size[py]:
            self.parent[py] = px
            self.size[px] += self.size[py]
        else:
            self.parent[px] = py
            self.size[py] += self.size[px]
        
        self.cnt -= 1
        
class Solution:
    def removeStones(self, stones: List[List[int]]) -> int:
        n = len(stones)
        uf = UnionFind(n)
        
        #用两个记录对应行和列出现过的石头(stones的索引值)
        row = {}
        col = {}
        
        for i, (r, c) in enumerate(stones):
            if r in row:
                uf.merge(i, row[r])
            if c in col:
                uf.merge(i, col[c])
            
            row[r], col[c] = i, i
        
        return n - uf.cnt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值