岛屿数量问题

新手小白第一次写博客,写的不好多多见谅。

今天第一天刷LeetCode上的题目,遇到了一个岛屿数量问题。先看题目:

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/number-of-islands

示例 1:

输入:
11110
11010
11000
00000
输出: 1

示例 2:

输入:
11000
11000
00100
00011
输出: 3
解释: 每座岛屿只能由水平和/或竖直方向上相邻的陆地连接而成。

看到这个题目,首先想到了逐元素遍历。但是思考了一会儿,发现题目并没有想象中的那么简单。于是改换思路,看着这个二位数组,突然联想到了老师上课的时候讲到的DFS的例子:

对以下无向图进行DFS并输出最终结果。
岛屿数量问题_第1张图片

这个问题对当时刚开始学数据结构的我来说,对着这个图画路径非常简单,但是一旦要是写代码就要费老大的功夫(惭愧.jpg)。

回到这个题目上来,类比上文提到的例子,我们就可以想出一种DFS的算法:
1.逐元素遍历,找到第一个为1的“岛屿”,并把岛屿数量+1。

1 1 1 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

2.将这个元素的值设为0,之后对这个元素进行DFS:

0 1 1 0 0
1 1 0 0 0
0 0 1 0 0
0 0 0 1 1

3.重复第二步,直到“一小片岛屿”上的1全部被发现并被改为0为止:

0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 1

4.之后继续进行第一步:

0 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 1

5.最终遍历结束,该算法结束,得到最终结果。

算法代码:(C++实现)

class Solution {
     
private:
void dfs(vector<vector<char>>& grid, int r, int c){
     
    grid[r][c] = 0;//将当前元素的值赋为0
    if(r-1 >= 0&&grid[r-1][c] == '1') 
    	dfs(grid, r-1, c);
    if(r+1 < grid.size()&&grid[r+1][c] == '1') 
    	dfs(grid, r+1, c);
    if(c-1 >= 0&&grid[r][c-1] == '1') 
    	dfs(grid, r, c-1);
    if(c+1 < grid[0].size()&&grid[r][c+1] == '1') 
    	dfs(grid, r, c+1);
}

public:
    int numIslands(vector<vector<char>>& grid) {
     
        int nums = 0;//岛屿数量

        int i,j;
        for(i = 0; i < grid.size(); i++){
     
            for(j = 0; j < grid[0].size(); j++){
     //逐元素进行遍历
                if(grid[i][j] == '1'){
     //如果发现有1的元素,那么说明发现了“新岛屿”,岛屿数+1.
                    ++nums;
                    dfs(grid, i, j);
                }
            }
        }
        return nums;
    }
};

输出结果:
岛屿数量问题_第2张图片
同样的,我们也可以使用BFS或者并查集的方法实现,有时间可以再研究研究。
PS:做题过程中还出了点小插曲,在这句话中

if(grid[i][j] == '1')

本来写的是

if(grid[i][j] == 1)

明明写完整个算法,自己也没找到啥问题,但就是不通过,后来看了一眼输入样例,才发现并不是int类型的输入,是真的粗心(啥时候能改过来啊啊啊…)。

练了LeetCode之后才发现自己是真的菜鸡一枚。。。以后争取每日一题吧。

你可能感兴趣的:(LeetCode刷题,算法,c++,leetcode,dfs)