hw面试题拾遗:统计大陆数量
这个本来应该在几个月前就处理,一直拖到了现在。题目描述很简单,一个二维平面被分割为小块,每块可能是陆地或者海洋。1表示陆地,0表示海洋。如果一个陆地区块的上\下\左\右是一块陆地,那么它们就会被看成是一个大陆。给定数组表示各区块,统计出有几块大陆。
关于这道题,当时给出题目的时候还愣了一会儿,因为在笔试部分做过类似的题目。我一开始的思路时:从左上开始遍历数组,如果当前区块是陆地,那么就用DFS和递归,继续对当前区块的右侧和下侧区块进行检测,直到检测不到陆地为止。这个思路其实有个严重问题:如果有块大陆,它的右上角凸出来一块,只对它的右侧和下侧进行dfs,那么它左下的部分就会被忽略,导致被识别成两块大陆。所以还是对四个方向都进行DFS。
用C写有一个隐藏的问题:C里面支持malloc动态申请的数组,或者直接用内置的数组。在主函数传递参数时,动态数组对应malloc,在子函数的形参里对应用int **。如果用的是静态数组,那么在形参中就写int array[][],第一个框可以不写,第二个框内肯定要写,c不能自动判断具体的形状。在实际使用时,最好使用C++的STL库自带的array,可以很方便地进行处理。但是如果用C,那最好使用动态数组,或者自己定义一个合适的结构体。在这里用静态数组展示一下算法的思路:
#include <stdio.h> void dfs(int map[5][6],int locate_x,int locate_y,int m,int n) { printf("进入dfs,当前位置%d,%d\n",locate_x,locate_y); if(locate_x<0 || locate_y<0|| locate_x>=m || locate_y>=n || map[locate_x][locate_y]==0) { return ; } map[locate_x][locate_y]=0; dfs(map,locate_x+1,locate_y,m,n); dfs(map,locate_x-1,locate_y,m,n); dfs(map,locate_x,locate_y+1,m,n); dfs(map,locate_x,locate_y-1,m,n); } int Solution(int map[5][6],int m,int n) { int num=0; int i,j;
for(i=0;i<m;i++) { for(j=0;j<n;j++) { if(map[i][j]==1) { printf("处理第%d行%d列\n",i,j); num++; dfs(map,i,j,m,n); printf("结束一次检查,当前状态:\n"); } } }
return num; } int main() { int map[5][6]={{1,1,1,1,1,0},{1,0,0,0,0,0},{1,0,0,0,1,0}, {0,0,1,1,1,0},{0,0,0,1,0,0}}; int i,j; for(i=0;i<5;i++) { for(j=0;j<6;j++) printf("%d ",map[i][j]); printf("\n"); } int res=Solution(map,5,6); printf("%d",res); }
一开始写解法的时候走入了一个误区,就是在考虑各种特殊情况应该怎么处理,要不要判断完当前位置是否为边界后再判断它的上下左右在不在界内,是不是首个点,等待。这样的想法导致算法判断被写的过于复杂。后来在gpt解释下我才反应过来,不需要纠结这些情况,如果当前区块是陆地,直接进入四个方向的DFS就行了,把越界和海洋区块判断都写在前面,这样DFS越界也没有关系,进入函数后就直接返回了,不会报错Segment Default。