【LeetCode】947、移除最多的同行或同列石头

【LeetCode】947、移除最多的同行或同列石头


一、并查集

1.1 并查集

只要可以连通则可组成集合, 集合内可只剩一个石头, 并查集的集合数就是最终石头的个数

因为只要能 连通的石头, 可只剩余一个, 即从边缘开始消除即可
即一个集合只剩一个石头, 所以返回并查集的数量即可

首先, 每个石头编号 0, 1, …, n-1
初始时, 每个石头单独成为一个集合

然后, 用两个哈希表, 行哈希表记录该行第一次出现的石头编号, 列哈希表记录该列第一次出现的石头编号
然后, 遍历每个石头,

  • 若该石头的横坐标是第一次出现, 则加入行哈希表; 否则 将该石头编号 和 改行第一次出现的石头编号 这两个集合合并
  • 若该石头的纵坐标是第一次出现, 则加入行哈希表; 否则 将该石头编号 和 改列第一次出现的石头编号 这两个集合合并
    最终, 集合的数量, 就是最终剩余的石头个数
    则 n - sets 则为需移除的石头个数
// go
var sets int
var father [1000]int
var rowFirst = make(map[int]int) // key: 行号(0..10^4), value: 石头编号(0..1000)
var colFirst = make(map[int]int) // key: 列号(0..10^4), value: 石头编号(0..1000)

func removeStones(stones [][]int) int {
    n := len(stones)
    build(n)
    for i, stone := range stones {
        row, col := stone[0], stone[1]
        if igot, ok := rowFirst[row]; !ok {
            rowFirst[row] = i
        } else {
            union(i, igot) // 合并 两个石头编号 所在的集合
        }
        if igot, ok := colFirst[col]; !ok {
            colFirst[col] = i
        } else {
            union(i, igot)
        }
    }
    return n - sets
}

func build(n int) {
    clear(rowFirst)
    clear(colFirst)
    for i := range n {
        father[i] = i
    }
    sets = n
}

func find(i int) int { // 扁平化
    if father[i] != i {
        father[i] = find(father[i])
    }
    return father[i]
}

func union(a, b int) {
    fa, fb := find(a), find(b)
    if fa != fb {
        father[fa] = fb
        sets--
    }
}

参考 左神 并查集

二、多语言解法

C p p / G o / P y t h o n / R u s t / J s / T s Cpp/Go/Python/Rust/Js/Ts Cpp/Go/Python/Rust/Js/Ts

// cpp
// go 同上
# python
// rust
// js
// ts
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

呆呆的猫

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

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

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

打赏作者

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

抵扣说明:

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

余额充值