947. 移除最多的同行或同列石头(并查集)

该博客介绍了如何利用并查集数据结构解决一个算法问题,即在二维平面上,计算移除最多同行或同列的石头的方法。通过创建并查集,将同一行或同一列的石头连接,并最终计算连通分量来确定可移除的石头数量。示例展示了如何应用这个算法,并给出了具体的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.heu.wsq.leetcode.bingchaji;

import java.util.HashMap;
import java.util.Map;

/**
 * 947. 移除最多的同行或同列石头
 * @author wsq
 * @date 2021/1/15
 * 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] 不能移除,因为它没有与另一块石头同行/列。
 *
 * 链接:https://leetcode-cn.com/problems/most-stones-removed-with-same-row-or-column
 */
public class RemoveStones {
    /**
    * 计算出由石头坐标构成的图的连通分量是多少,然后石头的总数减去连通分量数目,就是能去除最多石头的数量
    */
    public int removeStones(int[][] stones){
        int n = stones.length;
        if (n == 0){
            return 0;
        }
        UnionFind unionFind = new UnionFind();
        for (int[] stone: stones){
            unionFind.union(stone[0] + 10000, stone[1]);
        }
        return n - unionFind.getCount();
    }
    private class UnionFind{
        private Map<Integer, Integer> parent;
        private int count;

        public UnionFind(){
            this.parent = new HashMap<>();
            this.count = 0;
        }

        private int find(int x){
            if (!parent.containsKey(x)){
                parent.put(x, x);
                count++;
            }
            int r = x;
            while (r != this.parent.get(r)){
                r = this.parent.get(r);
            }
            int k = x;
            while (k != r){
                int tmp = this.parent.get(k);
                this.parent.put(k, r);
                k = tmp;
            }
            return r;
        }

        private void union(int x, int y){
            int rootX = find(x);
            int rootY = find(y);
            if (rootX == rootY){
                return;
            }
            this.parent.put(rootX, rootY);
            count--;
        }

        public int getCount(){
            return this.count;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值