947. Most Stones Removed with Same Row or Column

问题:

在坐标系中,给定一组坐标点。

我们假设,可以删除一个点,若存在与该点,x坐标相同or y坐标相同的其他点。

删除动作连续进行,最多可以有多少次删除动作?

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

 

解法:并查集(Disjoint Set)

由本题题意可知:

拥有相同x坐标 or y坐标的点,可以进行删除动作。

我们将这些点连为一个组,从边缘开始删除,即可使删除动作最多,为point总数-1,最后留下一个点。

那么每个联通组,最后都剩下一个点,

总共的删除动作则为,总点数-联通组个数

连通图问题,仍使用 并查集 来求解。

对每一个点,去判断已遍历过的点,是否与自己联通,若联通,则merge

最后计算联通组个数。

 

代码参考:

 1 class Solution {
 2 public:
 3     int removeStones(vector<vector<int>>& stones) {
 4         DisjointSet DS(stones.size());
 5         for(int i=1; i<stones.size(); i++) {
 6             for(int j=0; j<i; j++) {
 7                 if(stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1]) {
 8                     DS.merge(i,j);
 9                 }
10             }
11         }
12         //each group may leave 1 point, number of moves is sum(group point)-1
13         //move from leaf node. can make number of moves lagger.
14         return stones.size()-DS.getGroupCount();
15     }
16 };

 

并查集 代码参考:

 1 class DisjointSet {
 2 public:
 3     DisjointSet(int n):root(n,0), rank(n,0) {
 4         for(int i=0; i<n; i++) {
 5             root[i] = i;
 6         }
 7     }
 8     int find(int i) {
 9         if(i!=root[i]) {
10             root[i] = find(root[i]);
11         }
12         return root[i];
13     }
14     bool merge(int x, int y) {
15         int x_root = find(x);
16         int y_root = find(y);
17         if(x_root == y_root) return false;
18         if(rank[x_root] > rank[y_root]) {
19             root[y_root] = x_root;
20         } else if(rank[y_root] > rank[x_root]) {
21             root[x_root] = y_root;
22         } else {
23             root[x_root] = y_root;
24             rank[y_root] ++;
25         }
26         return true;
27     }
28     int getGroupCount() {
29         int res=0;
30         for(int i=0; i<root.size(); i++) {
31             if(i==root[i]) res++;
32         }
33         return res;
34     }
35 private:
36     vector<int> root;
37     vector<int> rank;
38 };

 

posted @ 2020-08-09 17:08  habibah_chang  阅读(105)  评论(0编辑  收藏  举报