题目:给定一个由“1”(陆地)和“0”(水)组成的二维网格,计算岛屿的数量。一个岛屿被水包围,并与相邻的陆地水平或垂直相连。您可以假设网格的所有四个侧面都被水包围。给定“1”(陆地)和“0”(水)的二维网格图,计算岛屿的数量。岛屿四面环水,由相邻陆地水平或垂直连接而成。您可以假设网格的所有四个边缘都被水包围。例1:输入:11110110101100000000输出:1例2:输入:11000110000010000011输出:3解题思路:首先理解岛的定义:一片1被全0包围的就是岛。(注意:网格数组中的1和0都是char字符,不是整数)例1中的所有1可以连在一起,即所有1组成一个岛。例2中的三个岛:左上角4个1,中间1个1,右下角1个1,分别组成三个岛。Floodfill算法是一种经典的算法,从一个区域中提取若干个相连的点,以将它们与其他相邻区域区分开来(或者将它们染成不同的颜色)。它之所以得名,是因为它的理念类似于洪水从一个区域蔓延到所有可达区域。在GNUGo和Minesweeper中,FloodFill算法用于计算需要清除的区域。从上面的定义可以看出,这道题是一个典型的Floodfill算法类型的例题,将小岛从水里分离出来,并染上特定的颜色,以记录小岛已经堆积。每个岛都可以看作是一个连接的节点。只需要遍历所有连接的节点,并标记一个特殊的值来记录该节点已经被访问过。当遍历完后,证明找到了一个岛。三种解题方法:DFS(深度优先搜索):从1的根节点开始访问,从每个相邻的1节点向下访问到顶点(被水包围),依次访问其他相邻的1节点到VertexBFS(广度优先搜索):从根节点1开始访问,每次访问一个节点,直到访问完最后一个顶点为止:也称为联合搜索数据结构,因为它主要由联合,查找两个流程实现:查找:判断元素属于哪个子集。它可以用来判断两个元素是否属于同一个子集。联合:将两个子集合并成同一个集合。对于这道题,先用一个根节点1作为初始节点,判断周围节点是否为1,如果是则新建一个集合,并以此节点作为父节点。然后遍历下一个结点,如果为1,则找到该结点的父结点(即第一个结点),将该结点周围所有带1的结点的父结点指向该结点的父结点,并以此类推,直到区块岛的All1节点加入同一个集合。最后的集合数(父节点数)就是孤岛数DFS:时间复杂度:O(M×N),其中M和N分别为行数和列数。空间复杂度:最坏情况下O(M×N),此时整个格子都是land,深度优先搜索的深度达到M×N。Java:classSolution{publicintnumIslands(char[][]grid){if(grid==null||grid.length==0)return0;introw=grid.length,columns=grid[0].length,count=0;for(inti=0;i=row||j>=columns||grid[i][j]=='0')return;//基线条件grid[i][j]='0';//设置遍历点为0dfs(grid,i+1,j,row,列);dfs(网格,i,j+1,行,列);dfs(网格,i-1,j,行,列);dfs(网格,i,j-1,行,列);}}Python:类解决方案:defnumIslands(self,grid:List[List[str]])->int:如果不是网格或len(grid)=='o':返回0行,columns=len(grid),len(grid[0])count=0foriinrange(row):forjinrange(columns):如果grid[i][j]=='1':self.dfs(grid,i,j,row,columns)count+=1returncountdefdfs(self,grid:List[List[str]],i:int,j:int,row:int,columns:int):如果i>=rowori<0orj>=columnsorj<0orgrid[i][j]=='0':returngrid[i][j]='0'self.dfs(grid,i-1,j,row,columns)self.dfs(grid,i,j-1,row,columns)self.dfs(grid,i+1,j,row,columns)self.dfs(grid,i,j+1,row,columns)BFS:时间复杂度:O(M×N),其中M和N分别为行数和列数复杂度:O(min(M,N)),在最坏的情况下(所有土地),队列的大小最多可达min(M,N)。Java:classSolution{publicintnumIslands(char[][]grid){if(grid==null||grid.length==0)return0;introw=grid.length,columns=grid[0].length,count=0;for(inti=0;iloc=newLinkedList<>();//队列暂存值为1的点loc.add(i*columns+j);//暂存点位置,也可以用A[i,j]数组表示,但占用空间会翻倍while(!loc.isEmpty()){intid=loc.remove();//移除位置intr=id/columns,c=id%columns;//分解位置得到索引if(r-1>=0&&grid[r-1][c]=='1'){loc.add((r-1)*列+c);网格[r-1][c]='0';}if(r+1=0&&grid[r][c-1]=='1'){loc.add(r*columns+c-1);网格[r][c-1]='0';}if(c+1int:ifnotgridorlen(grid)=='o':return0row,columns=len(网格),len(网格[0])count=0foriinrange(row):forjinrange(columns):ifgrid[i][j]=='1':self.bfs(grid,i,j,row,columns)count+=1返回计数defbfs(self,grid:List[List[str]],i:int,j:int,row:int,columns:int):queue=collections.deque()queue.append((i,j))#位置以元组的形式存储在队列中whilequeue:r,c=queue.popleft()如果r+1=0且grid[r-1][c]=='1':queue.append((r-1,c))grid[r-1][c]='0'如果c+1<列且网格[r][c+1]=='1':队列。append((r,c+1))grid[r][c+1]='0'如果c-1>=0并且grid[r][c-1]=='1':queue.append((r,c-1))grid[r][c-1]='0'andCheckset:mergesearch的解决方案繁琐无味,效率很低。以下java代码引用自LeetCode简单了了解其思路扩展一下思路即可:Java:classSolution{classUnionFind{intcount;//计算int[]parent;int[]等级;publicUnionFind(char[][]grid){count=0;intm=grid.length,n=grid[0].length;parent=newint[m*n];rank=newint[m*n];for(inti=0;irank[rooty]){父母[rooty]=rootx;}elseif(rank[rootx]=0&&grid[i-1][j]=='1')uf.union(i*columns+j,(i-1)*columns+j);if(i+1=0&&grid[i][j-1]=='1')uf.union(i*columns+j,i*columns+j-1);if(j+1