Leetcode | 947. Most Stones Removed with Same Row or Column [Union-Find/DPS]

Problem

https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/

分析

https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/discuss/197668/Count-the-Number-of-Islands-O(N)

本质是个连通图问题,最大移动石头的个数 = total - islands

解法:Union-Find 或者 DFS

注意:

  • 题目有ij的范围以及stones长度范围,需要注意空间使用大小,2D转1D的索引范围过大,存储上考虑用HashMap代替数组;
  • String作为key是一个新思路,避免了每次转换1D;
  • 需要使用权重来避免UF树过高

解法

public class MostStonesRemovedWithSameRowOrColumn {
    private final Map<Integer, String> rows = new HashMap<>();
    private final Map<Integer, String> cols = new HashMap<>();
    private Map<String, String> union;
    private Map<String, Integer> height;
    private int rootsTotal = 0;
    private int stonesTotal = 0;

    public int removeStones(int[][] stones) {
        union = new HashMap<>();
        height = new HashMap<>();
        for (int[] stone : stones) {
            int i = stone[0];
            int j = stone[1];
            String index = i + " " + j;
            union.put(index, index);
            height.put(index, 0);
        }
        stonesTotal = stones.length;
        rootsTotal = stones.length;
        for (int[] stone : stones) {
            int i = stone[0];
            int j = stone[1];
            String index = i + " " + j;
            union.put(index, index);
            if (rows.putIfAbsent(i, index) != null) {
                union(index, rows.get(i));
            }
            if (cols.putIfAbsent(j, index) != null) {
                union(index, cols.get(j));
            }

        }
        return stonesTotal - rootsTotal;
    }

    private String root(String i) {
        while (union.get(i) != i) {
            i = union.get(i);
        }
        return i;
    }

    private void union(String i, String j) {
        if (!connected(i, j)) {
            String rootI = root(i);
            String rootJ = root(j);
            if (height.get(rootI) < height.get(rootJ)) {
                union.put(rootI, rootJ);
                Integer h = height.get(rootJ);
                height.put(rootJ, ++h);
            } else {
                union.put(rootJ, rootI);
                Integer h = height.get(rootI);
                height.put(rootI, ++h);
            }
            rootsTotal--;
        }
    }

    private boolean connected(String i, String j) {
        String rootI = root(i);
        String rootJ = root(j);
        return rootI.equals(rootJ);
    }

    public static void main(String[] args) {
        int[][] stones = new int[][]{{0, 0}, {0, 1}, {1, 0}, {1, 2}, {2, 1}, {2, 2}};
        MostStonesRemovedWithSameRowOrColumn m = new MostStonesRemovedWithSameRowOrColumn();
        StdOut.println(m.removeStones(stones));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值