1. 程式人生 > >LeetCode 827.最大人工島 Making A Large Island

LeetCode 827.最大人工島 Making A Large Island

題目連結

二維數組裡,1代表陸地,0代表海洋。

我們最多隻能將一個0(海洋)變成1(陸地)。

進行填海後,地圖上最大的島嶼面積是多少?(上、下、左、右四個方向相連的1可形成島嶼)

例如:[[1,0],[0,1]],最大島嶼面積是3(將其中一個0變成1)

思路1:

1、將其中一個位置0變成1,然後在該位置進行深搜,另外用一個數組作為標記位,深搜的過程中統計陸地的個數,既是島的面積。

程式碼如下:

class Solution {
public:
   int a[50][50];//標記位
    void clear(int X,int Y)//標記為清零
    {
        for(int i=0;i<X;i++)
        {
            for(int j=0;j<Y;j++)
            {
                a[i][j]=0;
            }
        }
    }
    void search(vector<vector<int>>& grid,int x,int y,int& sum)//深搜,x y為位置,sum為大陸的個數
    {
        int X=grid.size();
        int Y=grid[0].size();
        if(grid[x][y]==1&&a[x][y]==0)
        {
            sum++;
            a[x][y]=1;
            if(x-1>=0)  search(grid,x-1,y,sum);//四個方向
            if(x+1<X)  search(grid,x+1,y,sum);
            if(y-1>=0)  search(grid,x,y-1,sum);
            if(y+1<Y)  search(grid,x,y+1,sum);
        }
    }
    int largestIsland(vector<vector<int>>& grid) {
        int X=grid.size();
        int Y=grid[0].size();
        int i,j;
        int sum,max=0;
        for(i=0;i<X;i++)
        {
            for(j=0;j<Y;j++)
            {
                if(grid[i][j]==0)
                {
                    grid[i][j]=1;//填海
                    clear(X,Y);
                    sum=0;
                    search(grid,i,j,sum);
                    grid[i][j]=0;//不填海
                    if(max<sum)max=sum;
                }
            }
        }
        if(max==0)  max=X*Y;//沒有海,只有陸地的情況
        return max;
    }
};

思路2:

1、思路1中,每次找到一個0,都要進行一次深搜,那可不可以簡化一下呢。

2、對於每一個0(海),只要知道它上下左右四個方向的島的面積,就可以通過相加,獲得填海後的大島的面積。

3、問題就在於,對於每一個0(海),怎麼知道它上下左右四個方向的島是同一個島,還是不相同的島。

4、於是,首先先對島分類編號,同時統計不同島的面積。

程式碼如下:

class Solution {
public:
    int a[50][50]={0};//對島分類編號
    int area[700]={0};//不同編號的島對應不同的面積
    int islandnum=0;//編號
    void search(vector<vector<int>>& grid,int x,int y)
    {
        int X=grid.size();
        int Y=grid[0].size();
        if(grid[x][y]==1&&a[x][y]==0)
        {
            area[islandnum]++;//累計相同編號的島的陸地
            a[x][y]=islandnum;//給陸地附上編號
            if(x-1>=0)  search(grid,x-1,y);//四個方向
            if(x+1<X)  search(grid,x+1,y);
            if(y-1>=0)  search(grid,x,y-1);
            if(y+1<Y)  search(grid,x,y+1);
        }
    }
    int largestIsland(vector<vector<int>>& grid) {    
        int X=grid.size();
        int Y=grid[0].size();
        for(int i=0;i<X;i++)
        {
            for(int j=0;j<Y;j++)
            {
                if(grid[i][j]==1&&a[i][j]==0)
                {
                    islandnum++;//找到的第一個島,應該從編號1開始
                    search(grid,i,j);
                }
            }
        }
        int b[4]={0};//海的四個方向的島的編號,上下左右
        int maxsum=0,sum;
        for(int i=0;i<X;i++)
        {
            for(int j=0;j<Y;j++)
            {
                if(grid[i][j]==0)
                {
                    sum=1;//畢竟填海嘛,面積得從1算起
                    if(i-1<0)  b[0]=0;
                    else b[0]=a[i-1][j];//上沒有越界,則附值上方的島的編號
                    if(i+1>=X)  b[1]=0;
                    else b[1]=a[i+1][j];//同理
                    if(j-1<0)  b[2]=0;
                    else b[2]=a[i][j-1];//同理
                    if(j+1>=Y)  b[3]=0;
                    else b[3]=a[i][j+1];//同理
                    for(int k=0;k<4;k++)
                    {
                        if(b[k]!=0)
                        {
                            sum+=area[b[k]];//加上該方向的島的編號的面積
                            for(int l=k+1;l<4;l++)
                            {
                                if(b[l]==b[k])  b[l]=0;//保證四個方向不會出現相同編號的島
                            }
                            //b[k]=0;
                        }
                        if(sum>maxsum)  maxsum=sum;
                    }
                }
            }
        }
        if(maxsum==0)  maxsum=X*Y;//沒有海的情況下
        return maxsum;
    }
};