LeetCode 题解工作台

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

n 块石头放置在二维平面中的一些整数坐标点上。每个坐标点上最多只能有一块石头。 如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。 给你一个长度为 n 的数组 stones ,其中 stones[i] = [x i , y i ] 表示第 i 块石头的位置,返回 可以移除的石子…

category

4

题型

code_blocks

5

代码语言

hub

3

相关题

当前训练重点

中等 · 图·DFS·traversal

bolt

答案摘要

我们可以用并查集维护石头之间的关系。如果两块石头在同一行或同一列,我们就认为它们之间有关系,可以通过并查集将它们连接起来。最后,我们统计并查集中有多少个连通分量,这个数值就是可以剩余的石头的数量,那么总共可以移除的石头数量就是石头总数减去剩余的石头数量。我们也可以在合并的时候,记录成功合并的次数,这个次数就是可以移除的石头的数量。 时间复杂度 $O(n^2 \times \alpha(n))$,空…

Interview AiBox logo

Interview AiBox 实时 AI 助手,陪你讲清 图·DFS·traversal 题型思路

试试 AiBox 面试助手arrow_forward
description

题目描述

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

示例 3:

输入:stones = [[0,0]]
输出:0
解释:[0,0] 是平面上唯一一块石头,所以不可以移除它。

 

提示:

  • 1 <= stones.length <= 1000
  • 0 <= xi, yi <= 104
  • 不会有两块石头放在同一个坐标点上
lightbulb

解题思路

方法一:并查集

我们可以用并查集维护石头之间的关系。如果两块石头在同一行或同一列,我们就认为它们之间有关系,可以通过并查集将它们连接起来。最后,我们统计并查集中有多少个连通分量,这个数值就是可以剩余的石头的数量,那么总共可以移除的石头数量就是石头总数减去剩余的石头数量。我们也可以在合并的时候,记录成功合并的次数,这个次数就是可以移除的石头的数量。

时间复杂度 O(n2×α(n))O(n^2 \times \alpha(n)),空间复杂度 O(n)O(n)。其中 nn 为石头的数量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class UnionFind:
    def __init__(self, n):
        self.p = list(range(n))
        self.size = [1] * 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, a, b):
        pa, pb = self.find(a), self.find(b)
        if pa == pb:
            return False
        if self.size[pa] > self.size[pb]:
            self.p[pb] = pa
            self.size[pa] += self.size[pb]
        else:
            self.p[pa] = pb
            self.size[pb] += self.size[pa]
        return True


class Solution:
    def removeStones(self, stones: List[List[int]]) -> int:
        uf = UnionFind(len(stones))
        ans = 0
        for i, (x1, y1) in enumerate(stones):
            for j, (x2, y2) in enumerate(stones[:i]):
                if x1 == x2 or y1 == y2:
                    ans += uf.union(i, j)
        return ans
speed

复杂度分析

指标
时间O(n)
空间O(n + 20002)
psychology

面试官常问的追问

外企场景
  • question_mark

    Focus on graph traversal patterns to explore the problem space.

  • question_mark

    Test the candidate's understanding of DFS and its application in a graph traversal problem.

  • question_mark

    Look for efficiency in using Union-Find to handle large inputs with minimal time complexity.

warning

常见陷阱

外企场景
  • error

    Failing to optimize the search process and running into time limit errors with larger inputs.

  • error

    Overcomplicating the graph representation, leading to unnecessary space usage or slower performance.

  • error

    Not handling edge cases like when there’s only one stone, which cannot be removed.

swap_horiz

进阶变体

外企场景
  • arrow_right_alt

    Consider problems where the stones can be removed in a different pattern, such as only removing stones from the same row or same column at once.

  • arrow_right_alt

    Explore the problem with varying input sizes to test performance and scalability.

  • arrow_right_alt

    Change the problem such that stones can be removed if they are in the same diagonal, testing how candidates adapt their graph traversal logic.

help

常见问题

外企场景

移除最多的同行或同列石头题解:图·DFS·traversal | LeetCode #947 中等