947. Most Stones Removed with Same Row or Column/ Union Find

https://leetcode.com/problems/most-stones-removed-with-same-row-or-column/
通过这道例题来复习理解Union Find算法
碰到棋盘类型的题目不知如何下手的情况下都可以想想是不是符合Union Find的阶梯逻辑呢;

On a 2D plane, we place stones at some integer coordinate points.  
Each coordinate point may have at most one stone.
Now, a move consists of removing a stone that shares a column 
or row with another stone on the grid. 
What is the largest possible number of moves we can make?
Example 1:
Input: stones = [[0,0],[0,1],[1,0],[1,2],[2,1],[2,2]]
Output: 5

Example 2:
Input: stones = [[0,0],[0,2],[1,1],[2,0],[2,2]]
Output: 3

Example 3:
Input: stones = [[0,0]]
Output: 0 

Note:
1 <= stones.length <= 1000
0 <= stones[i][j] < 10000

先不说这道题如何使用Union Find, 先来讲一下什么是Union Find;
Union Find是一种算法,根本逻辑是有很多nodes,现在呢我们要以某种方式将他们划分为不同的group。Union Find算法顾名思义有两个最重要的Function,其一是Union其二是Find
FunctionFind可以寻找到某个节点的父节点,子节点跟父节点的关系是他们都同属于一个group。最理想的效果是所有的在同一个group里的节点都指向共同的root根节点(实际算法中这个效果不会一直保持,否则会增加耗时)。当然也有可能碰到新节点,那么对于新节点而言自己就是自己的父节点,这也就是对新节点的默认操作。
FunctionUnion的逻辑是宣告两个节点同属于一个group。在Union方法中我们需要调用Find方法找到两个节点当前的父节点,然后将他们合并。
在Union Find整个结构建好以后,我们可以对任意两个节点进行query,看他们是否属于同一个group,同时我们也能获取一共有多少个group存在。

好了,现在回到这道题,可以使用Union Find方法来完成。具体代码如下:

class Solution {
    Map map = new HashMap<>();
    int island = 0;
    
    public int removeStones(int[][] stones) {
        if(stones.length <= 1){
            return 0;
        }
        for(int i = 0; i < stones.length; i++){
            union(stones[i][0], stones[i][1] + 10000);
        }
        return stones.length - island;
        
    }
    
    private int find(int i){
        if(map.putIfAbsent(i,i) == null){
            this.island ++;
            return i;  //对于新节点的默认操作
        }
        int j = i;
        while(map.get(j) != j){  //假如节点并不是一个group的根节点
            j = map.get(j);  //那么我们query到它的时候就更新成group的根节点root
        }  //一个group的root的特点是它的父节点就是自己
        map.put(i,j);
        return j;
    }
    
    private void union(int i, int j){
        i = find(i);  //这里需要保证find找到的是group根节点,否则算法逻辑会出错
        j = find(j);
        if(i != j){  //不等证明证明i和j之前处于不同的group
            island--;
            map.put(j, i);
        }
    }
    
}

你可能感兴趣的:(947. Most Stones Removed with Same Row or Column/ Union Find)