【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來尋找二維數組中被包圍的塊的方法。

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