美文网首页
Leetcode: Most Stones Removed wi

Leetcode: Most Stones Removed wi

作者: akak18183 | 来源:发表于2020-06-13 12:53 被阅读0次

    题目

    分析

    乍看之下,有点摸不着头脑。稍微举几个简单的例子,就能发现其中的规律。
    题目给出一个“相连”的概念,即行或者列相同,这里可以用坐标系来理解。
    那么,首先分析一些基本情况:

    • 当没有石头“相连”,那么无法做出符合题意的操作,是0;
    • 只有2个石头“相连”,能做出1个操作;
    • 3个石头“相连”,就是2个操作;
    • 可见,如果一组有n个石头相连,那么操作数就是n-1
    • 假如有两组,一组2相连,一组3相连,它们互相之间并不干涉,最后结果就是分别能进行操作的数目相加;
    • 假设总共有m个互不干涉的组,那么操作数总共就是(n(0)-1)+(n(1)-1)+...+(n(m-1)-1),其中n(i)代表第i组的石头个数。因为总共的石头个数是给定的,假设为N,那么可得最后的操作数就是(n(0)+...+n(m-1))-m = N-m。也就是说,问题转化为求总共有多少个互不相干的组
    • 要解决这个问题,连通图就是一个很直接的想法。但问题来了,我们一般运用的连通图是1维的,这个是2维的,怎么弄?假如强行开2维连通图,需要解决很多小问题,不是一时半会能写出无bug代码的,因此不如尝试把2维转化为1维。
    • 根据题意,坐标的x和y是需要区分开来的,因为两个石头(x1,y1)与(x2,y2),x或者y相等属于相连,但x1=y2这种可不算。
    • 最简洁的做法,就是把y加上一个值,让x和y不会重合就好。题目里给的值是10000.
    • 构造图只需要连通单个石头本身的x与y+10000就行了。假如与之前某个石头“相连”,连通的时候自然会发现。
    • 到这里,问题就解决了,参考代码如下:
    // T:O(NlogN) S:O(N)
    class Solution {
        public int removeStones(int[][] stones) {
            int N = stones.length;
            DSU dsu = new DSU(20000);
    
            for (int[] stone: stones)
                dsu.union(stone[0], stone[1] + 10000);
    
            Set<Integer> seen = new HashSet();
            for (int[] stone: stones)
                seen.add(dsu.find(stone[0]));
    
            return N - seen.size();
        }
    }
    
    class DSU {
        int[] parent;
        public DSU(int N) {
            parent = new int[N];
            for (int i = 0; i < N; ++i)
                parent[i] = i;
        }
        public int find(int x) {
            if (parent[x] != x) parent[x] = find(parent[x]);
            return parent[x];
        }
        public void union(int x, int y) {
            parent[find(x)] = find(y);
        }
    }
    

    相关文章

      网友评论

          本文标题:Leetcode: Most Stones Removed wi

          本文链接:https://www.haomeiwen.com/subject/hrmatktx.html