原题(Medium):
给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量。一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的。你可以假设网格的四个边均被水包围。
思路:递归
这题类型跟我们之前做过的一题单词搜索类似。所以我在看到这题之后,就想到了可以用与之相同的思路:建立一个代表搜索方向的数组,在当前坐标下,如果往某个方向移动一格是符合一定条件的,就往该方向移动一格,且是递归形式的移动。在这里条件就是不超越边界,且该方向上有岛屿可供移动,且是未被访问过的。如果4个方向都尝试完毕,就可以返回了。为了防止重复访问已经被访问过的岛屿格,需要一个访问数组做记录。在递归过程中,每前进一格(符合条件才会前进),就设置该格已被访问。
1 int xy[4][4] = { { 1,0 },{ 0,-1 },{ -1,0 },{ 0,1 } }; //代表搜索方向的数组 2 3 void helper(vector<vector<int>>& grid, int x, int y, vector<vector<bool>>& visited) 4 { 5 visited[y][x] = true; 6 for (int i = 0; i < 4; i++) 7 { 8 //以当前网格起点,尝试其四周能能否移动,能就继续递归移动,直至整座岛屿被访问完毕 9 int tempX = x + xy[i][0]; 10 int tempY = y + xy[i][1]; 11 //不超越边界,且该方向上有岛屿可供移动,且是未被访问过的 12 if (tempY >= 0 && tempY<grid.size() && tempX >= 0 && tempX<grid[0].size() && grid[tempY][tempX] && !visited[tempY][tempX]) 13 helper(grid, tempX, tempY, visited); 14 } 15 } 16 int numIslands(vector<vector<int>>& grid) { 17 vector<vector<bool>> visited(grid.size(), vector<bool>(grid[0].size(), false)); 18 19 int count = 0; 20 21 for (int i = 0; i<grid.size(); i++) 22 for (int j = 0; j< grid[0].size(); j++) 23 { 24 if (grid[i][j] && !visited[i][j]) 25 { 26 //主函数:从网格中查找每一个岛屿,只要发现一格陆地,整座岛屿都会在递归中被访问,那么在之后的查找中便不会再次访问 27 helper(grid, i, j, visited); 28 //每进来这里表示发现了一座岛屿,计数器+1 29 count++; 30 } 31 } 32 return count; 33 }