网络异常,图片无法展示
|
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
- 不会有两块石头放在同一个坐标点上
解题思路
本题其实就类似于消消乐游戏,当同行或同列有一个以上的石头,除了最后一个,都可以删除。
而且这个过程是可以递推的,所以我们可以把在同行或同列的石头放在一个集合,这样的一个集合中,只需要保留一块石头即可。
通过这种方式就可以获取到可移除的石头的数量。
因为过程中需要频繁对集合进行合并,以及获取石头所在集合,所以可以需要借助并查集解题。
如果你对 并查集
还不了解,可以看我这一篇文章 数据结构-并查集,文中介绍了并查集的概念、应用场景以及手写实现的全过程。
动画演示
网络异常,图片无法展示
|
代码实现
class UnionSet { constructor(n){ // 初始化节点数量数组 this.size = Array(n).fill(1); // 初始化集合列表,每一个节点为一个集合 this.list = Array(n); for(let i = 0;i<n;i++){ this.list[i] = i; } } // 递归获取元素所在集合根节点 find(x){ if(this.list[x] === x) return x; // 获取到元素所在集合根节点 const root = this.find(this.list[x]) // 将当前节点挂载为根节点子节点,压缩路径 this.list[x] = root; return root; } // 合并两个集合 merge(rootA,rootB){ // 如果 a 所在集合元素数量更多,将 b 所在集合合并到 a 所在集合 if(this.size[rootA]>this.size[rootB]){ this.list[rootB] = rootA; this.size[rootA] += this.size[rootB] }else{ // 反之将 a 所在集合合并到 b 所在集合 this.list[rootA] = rootB; this.size[rootB] += this.size[rootA] } } } var removeStones = function(stones) { // 获取石头数量 const len = stones.length, // 创建并查集实例 unionset = new UnionSet(len); // 初始化结果值 let res = 0; for(let i = 0;i<len-1;i++){ for(let j = i+1;j<len;j++){ if(stones[i][0]===stones[j][0]||stones[i][1]===stones[j][1]){ // 获取两个元素所在集合的根节点 const rootA = unionset.find(i),rootB = unionset.find(j) // 如果两个根节点不同,则进行合并,同时一次合并可以看做删除一个石头,结果值+1 if(rootA!==rootB){ res++; unionset.merge(rootA,rootB) } } } } // 返回结果值 return res; }; 复制代码
至此我们就完成了 leetcode-947-移除最多的同行或同列石头
如有任何问题或建议,欢迎留言讨论!