【LeetCode】Weekly Contest 162:Number of Closed Islands 判断孤岛

一、概述

输入一个二维数组,元素均为0或1,0表示陆地,1表示海洋,返回孤岛个数。孤岛定义为一连串的陆地,其上下左右均为海洋。孤岛不能与二维数组边缘相连。

服务器搞得我心态爆炸。本来这题可以提交的——那样我就1360/6058,而不是现在的1925/6058,前进600名呢。结果十一点五十开始连不上,气得我差点把电脑砸了。

二、分析

这个题第一眼我看到的时候是懵逼的:

什么叫孤岛啊?怎么判断孤岛啊?

然后发现了孤岛的特征:它是一坨连起来的0,周围全是1,注意只要上下左右四面,不用八方。

然后继续归纳,我挨着边缘,但三面环水的算不算啊?不算。只有严格四面环水的才算。

那么问题清楚了一些:和边缘挨着的叫陆地,陆地都不算。

我们可以先把陆地都找出来,再在其余的地方找孤岛。

怎么找陆地呢?这是个问题。可以先在二维数组,我们叫它地图吧,在地图最外圈走一圈,把所有的0标记为陆地,然后再去内部,和陆地相连的也是陆地。这样做。

如何实现“和陆地相连的也是陆地”?用DFS。DFS从一块陆地出发,之后只要遇到0,就标记为陆地,遇到1就返回。这点很重要。我们称一次DFS为一次污染。

要污染多少次呢?我们绕着地图最外面走一圈,碰到陆地,我们把它标记为-1吧,就开始污染。走完了也就污染完了。

现在看地图,其中有三种元素:-1:陆地;0:岛屿;1:海水。然后开始找岛屿。

找岛屿的方法和找陆地一样:我们这次要遍历一整张地图,遇到岛屿就开始污染,将其标记为t,每次污染完一个岛屿,t递增1。什么叫污染完岛屿呢?DFS完一次啊。当我们遍历完整张地图,那么就将所有的岛屿标记为t、t+1、t+2等等。

返回t即可。

这里有一个技巧,我们将t赋值为10,以和0,1,-1区分开。然后返回t-10即可。

代码如下:

class Solution {
    void DFS(vector<vector<int>>& g,int i,int j,int t)
    {
        if(i<g.size()&&j<g[0].size()&&g[i][j]==0)
        {
            g[i][j]=t;
            DFS(g,i,j+1,t);
            DFS(g,i+1,j,t);
            DFS(g,i,j-1,t);
            DFS(g,i-1,j,t);
        }
    }
    void DFS1(vector<vector<int>>& g,int i,int j,int t)
    {
        if(i<g.size()&&j<g[0].size()&&g[i][j]<=0)
        {
            g[i][j]=t;
            DFS(g,i,j+1,t);
            DFS(g,i+1,j,t);
            DFS(g,i,j-1,t);
            DFS(g,i-1,j,t);
        }
    }
public:
    int closedIsland(vector<vector<int>>& g) {
        int res=10;
        for(int i=0;i<g[0].size();i++)
        {
            if(g[0][i]==0)
                g[0][i]=-1;
            if(g[g.size()-1][i]==0)
                g[g.size()-1][i]=-1;
        }
        for(int i=0;i<g.size();i++)
        {
            if(g[i][0]==0)
                g[i][0]=-1;
            if(g[i][g[0].size()-1]==0)
                g[i][g[0].size()-1]=-1;
        }//标记地图周边的陆地
        for(int i=0;i<g.size();i++)
            for(int j=0;j<g[0].size();j++)
            {
                if(g[i][j]==-1)
                    DFS1(g,i,j,-1);
            }//污染所有陆地
        for(int i=1;i<g.size()-1;i++)
        {
            for(int j=1;j<g[0].size()-1;j++)
            {
                if(g[i][j]==0)
                {
                    DFS(g,i,j,res);
                    res++;//污染岛屿
                }
            }
        }
        return res-10;
    }
};

三、总结

这种题目第一次做,主要是思维的转换——能够找到解已经很好了,不要去奢求时间复杂度多么好。也学到了用DFS来寻找二维数组中被包围的块的方法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章