移除最多的同行或同列石头
刚学会markdown拿来练手
解法1:dfs遍历
Cow Picnic S
这两道题基本上是一样的,都是进行遍历查找。
将在同一行或者同一列的点建立成一张图,易知对于每一个联通的块,都可以将其逐渐删成一个点。因此,最后统计一下有多少个联通的块,就能知道最多可以去掉多少个点了。
class Solution {
public:
void dfs(vector<vector<int> >&graph, int x, vector<int>& vis){
vis[x] = true;
for(auto &y : graph[x])
if(!vis[y])
dfs(graph, y, vis);
}
int removeStones(vector<vector<int>>& stones) {
int n = stones.size();
vector<vector<int> > edge(n);
for(int i = 0; i < n; i ++){
for(int j = 0; j < n; j ++){
if(stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1])
edge[i].push_back(j);
}
}
vector<int>vis(n);
int cnt = 0;
for(int i = 0; i < n; i ++){
if(!vis[i]){
cnt ++;
dfs(edge, i, vis);
}
}
return n - cnt;
}
};
解法2:并查集
对于一个点,如果这个点的行和列都在之前还没有出现过,那么就将这个点设置为祖先节点,对于后续的一系列点如果和这个点在同一行或同一列,那么就把这些点连接到一起。
后面所有点同理。
最后只需要遍历一遍,统计一下有多少个并查集块,然后用总的点数一减就好了。
代码如下
class Solution {
public:
void init(vector<int>& fa, int n){
for(int i = 0; i < n; i ++)
fa[i] = i;
}
int find(vector<int>&fa, int x){
if(x == fa[x])
return x;
else return fa[x] = find(fa, fa[x]);
}
int removeStones(vector<vector<int>>& stones) {
int n = stones.size();
vector<int>fa(n);
init(fa, n);
for(int i = 0; i < n; i ++){
for(int j = i + 1; j < n; j ++){
if(stones[i][0] == stones[j][0] || stones[i][1] == stones[j][1])
if(find(fa, i) != find(fa, j))
fa[i] = fa[j];
}
}
int cnt = 0;
for(int i = 0; i < n; i ++)
if(fa[i] == i)
cnt ++;
return cnt;
}
};
有一说一,markdown还真挺好用