您的位置:首页 > 编程语言 > C语言/C++

Leetcode 200.岛屿的个数 C语言

2019-03-31 08:26 866 查看


这是一道队列与BFS的练习题,但由于我对队列与BFS的理解甚浅(差不多就停留在二叉树的层次遍历那),因此我没能从这个角度将这个问题解决了。但是回归问题本身,其实它要求解决的问题非常的明了,那就是求一个图中连通分量的个数。关于图的连通性,很自然的,我们想到使用并查集,于是问题的思考便可以展开了。

思考一:点具有两个坐标,我们如何用一个数来刻画这个点的位置呢?

Solution: 利用点的集合行列的连续性,第i个点的所在的行数可以用(i/gridColSize)来描述,所在的列数可以用(i%gridColSize)来描述。因此某行某列的点有了唯一对应的i。

int i, j, nums = 0;
int* arr = (int*)malloc(sizeof(int)*(gridRowSize*gridColSize));
int* tree = (int*)malloc(sizeof(int)*(gridRowSize*gridColSize));
for(i = 0 ;i < gridRowSize*gridColSize ;i++) {
arr[i] = grid[i/gridColSize][i%gridColSize] - '0';
tree[i] = i;}//将二维数组转换成一维数组(其实没什么必要,但是我个人会更直观),使用并查集判断两点是否连通。

思考二:如何判断两点间连通

Solution: 前面虽然已经提过,使用并查集便可以轻松解决这个问题,但我们还可以进行一个小小的优化。因为本题并不在意哪两点是否连接,它只是在意两点是否连通,因此我们把所有点都连向根节点便可以了。

思考三:怎么确定一个点的根节点呢?

Solution:由i的定义知,我们的遍历顺序是从左到右,再从上到下的 。所以我们只需要判断某点与上方以及左边的连通性即可。如果某点与上方的点连通,我们有 tree[i] = tree[i-gridColSize] ,这样便把第i个点与它的根节点连通了。如果某点与左边的点连通,我们有 tree[i] = tree[i-1] , 这样便也将第i个点与它的根节点连通了。

思考四:反“L”型该如何处理?

Solution: 如果一个点它既与上方连通也与左边连通出现了反向的“L”型。我们只需要确定一个优先级(比如我优先上方),然后再把之前的点全部遍历一遍,把所有根节点和左边的点相同的点的根节点全改成上方点的根节点即可。

for(i = 1;i < gridRowSize*gridColSize;i++){
if(i/gridColSize!=0 && arr[i] == 1 && grid[i/gridColSize-1][i%gridColSize] == '1'){
tree[i] = tree[i-gridColSize];
}//优先行数小的点做父节点。

if(i%gridColSize!=0 && tree[i]==i && arr[i] == 1 && grid[i/gridColSize][i%gridColSize - 1] == '1'){
tree[i] = tree[i-1];
}//末选列数小的点做父节点。

else if(i%gridColSize!=0 && tree[i]!=i && arr[i] == 1 && grid[i/gridColSize][i%gridColSize - 1] == '1'){
for(j=0;j<i;j++){
if(tree[j] == tree[i-1]) tree[j] = tree[i];
}
}//“反L”型Solution。
}

输出

for(i=0;i<gridRowSize*gridColSize;i++){
if(arr[i] == 1 && tree[i] == i)  nums++;
}//根节点的个数便是连通分支的个数,游戏结束。
free(arr);
free(tree);
return nums;

并查集学习:https://www.geek-share.com/detail/2523523700.html
相关题:gcd最小生成树

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: