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

少于 1 分钟读完

我们将石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。

每次 move 操作都会移除一块所在行或者列上有其他石头存在的石头。

请你设计一个算法,计算最多能执行多少次 move 操作?

示例

示例 1:

输入:stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
输出:5
示例 2:

输入:stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
输出:3
示例 3:

输入:stones = [[0,0]]
输出:0
 

提示:

1 <= stones.length <= 1000
0 <= stones[i][j] < 10000

解题思路

题目很抽象,当其实就是找连通图的个数,一共有2中方法:dfs和dsu(disjoint-set)

1. dfs

没有什么难度,遍历-压栈-弹出

import collections
class Solution:
    def removeStones(self, stones) -> int:
        X = collections.defaultdict(set)
        Y = collections.defaultdict(set)
        mmax = -1
        for x, y in stones:
            X[x].add(y)
            Y[y].add(x)
            mmax = max(mmax, x)
        
        count = 0
        for i in range(mmax+1):
            if i in X:
                count += 1
                stack = [i]
                while len(stack):
                    index = stack.pop()
                    Ys = X[index]
                    for j in Ys:
                        for k in Y[j]:
                            if k in X:
                                stack.append(k)
                    del X[index]
        return len(stones) - count

2. dsu

新知识点get。

并查集主要是find和union的操作(好像还有缩短路径的优化,这里没涉及到),题目x,y的范围在0-10000,所以可以用10000将它们隔开,用一个一维的数组来表示这个集合,主要的思想就是把x(0-10000)映射到y(10001-20000),在y空间上,不同节点还存在父子关系,最后只要数出父亲节点的个数就好了。

def removeStones(self, stones):
  class DSU:
    def __init__(self, N):
      self.p = list(range(N))

      def find(self, x):
        if self.p[x] != x:
          self.p[x] = self.find(self.p[x])
          return self.p[x]

        def union(self, x, y):
          xr = self.find(x)
          yr = self.find(y)
          self.p[xr] = yr

          N = len(stones)
          dsu = DSU(20000)
          for x, y in stones:
            dsu.union(x, y + 10000)
            print({dsu.find(x) for x, y in stones})
            return N - len({dsu.find(x) for x, y in stones})

分类:

更新时间: