[路飞] 947. 移除最多的同行或同列石头

93 阅读1分钟

题目描述

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

如果一块石头的 同行或者同列 上有其他石头存在,那么就可以移除这块石头。

给你一个长度为 n 的数组 stones ,其中 stones[i] = [xi, yi] 表示第 i 块石头的位置,返回 可以移除的石子 的最大数量。

解题思路

数据结构,算法

并查集,哈希表

思路

通过两个哈希表 xMap, yMap,记录每个坐标(x, y) 都存在哪些石子,这是我们用 O(1) 复杂度找到石子的关键

并查集中记录每个石子的联通情况,第 i 个项值表示 stones 的第 i 项的连通情况,最终我们找到的“可以移除的狮子的最大数量”就是 stones.length - 并查集集数量

过程

遍历所有的 stones[i]

根据 stones[i]x, y,连接 xMap, yMap 中具有同坐标的石头,merge 起来

在哈希表中记录本石头的 i

遍历并查集,计算 stones.length - 并查集集数量

代码

/**
 * @param {number[][]} stones
 * @return {number}
 */
var removeStones = function (stones) {
  const u = new UnionSet(stones.length)
  const xMap = {}
  const yMap = {}

  stones.forEach((item, index) => {
    const x = item[0]
    const y = item[1]

    if (xMap[x] !== undefined) {
      u.merge(xMap[x], index)
    }
    if (yMap[y] !== undefined) {
      u.merge(yMap[y], index)
    }

    xMap[x] = index
    yMap[y] = index
  })

  let cnt = 0
  for (let i = 0; i < stones.length; i++) {
    if (u.get(i) === i) cnt++
  }

  return stones.length - cnt
}

class UnionSet {
  constructor(n) {
    this.fa = []
    for (let i = 0; i < n; i++) {
      this.fa[i] = i
    }
  }

  get(x) {
    return (this.fa[x] = this.fa[x] === x ? x : this.get(this.fa[x]))
  }

  merge(a, b) {
    this.fa[this.get(a)] = this.get(b)
  }
}