在二維地圖上, 0
表明海洋, 1
表明陸地,咱們最多隻能將一格 0
海洋變成 1
變成陸地。數組
進行填海以後,地圖上最大的島嶼面積是多少?(上、下、左、右四個方向相連的 1
可造成島嶼)函數
示例 1:this
輸入: [[1, 0], [0, 1]] 輸出: 3 解釋: 將一格0變成1,最終連通兩個小島獲得面積爲 3 的島嶼。
示例 2:code
輸入: [[1, 1], [1, 0]] 輸出: 4 解釋: 將一格0變成1,島嶼的面積擴大爲 4。
示例 3:blog
輸入: [[1, 1], [1, 1]] 輸出: 4 解釋: 沒有0可讓咱們變成1,面積依然爲 4。
說明:io
1 <= grid.length = grid[0].length <= 50
0 <= grid[i][j] <= 1
思路:class
經過題目咱們尋找一種遍歷的方法,對每一個數字0,判斷若是將其填海,面積爲多少,記爲area
。容器
用中文敘述就是:grid
area初始化爲0 若是此海上面爲陸地,area+上面連成片的陸地面積。 若是此海右面爲陸地,area+右面連成片的陸地面積。 若是此海下面爲陸地,area+下面連成片的陸地面積。 若是此海左面爲陸地,area+左面連成片的陸地面積。
代碼表示則是:遍歷
if(g[i-1][j]==1)area+=上面連成片的陸地面積; if(g[i][j+1]==1)area+=右面連成片的陸地面積; if(g[i+1][j]==1)area+=下面連成片的陸地面積; if(g[i][j-1]==1)area+=左面連成片的陸地面積;
本題的目的就是找到這個最大的area
。
但是遍歷的時候會有兩個麻煩點
其實2好解決,每次查詢的時候進行邊界檢查便可。
可是1的解決方式就很複雜,個人解決方式是經過增長兩個記錄數組,給連成片的陸地進行編號,計算上下左右的陸地面積,若遇到有相同的陸地編號則不進行計算。
unsigned tag[50][50]={0}; /*用來記錄第X,Y塊屬於哪塊陸地片,若是是0則表示這塊屬於海洋,初始化所有爲0*/ int area[700]={0}; /*** 每一個塊號面積爲多少,記做area[tag_number]=the_area_of_this tag 也能夠用容器unordered_map<int,unsigned>area節省空間 ***/
舉個例子,好比有一海洋爲(X,Y),其中上面爲陸地編號爲1,右面爲陸地(編號爲1),下面的陸地編號也爲1(說明這塊土地與(X,Y)上面那塊土地相連),左面爲海(編號爲0)
以下圖畫的,則area只用加一個標記爲1的陸地面積其中一個就好了。
避開重複的數字有不少種方法,如unordered_map
,或者建一個大小爲4的數組,進行位運算這些都是一種方法,就不一一介紹了。
/*對代碼解釋在代碼的後面*/ class Solution { public: unsigned tag[50][50] = {0}; int area[700] = {0}; unsigned landNum = 0, X, Y; void search(const vector<vector<int>> &grid, const unsigned x, const unsigned y) { if (grid[x][y] == 1 && tag[x][y] == 0) { area[landNum]++; tag[x][y] = landNum; /*四個if是邊界檢查*/ if (x >= 1) search(grid, x - 1, y); if (x < X - 1) search(grid, x + 1, y); if (y >= 1) search(grid, x, y - 1); if (y < Y - 1) search(grid, x, y + 1); } } int largestIsland(vector<vector<int>> &grid) { unsigned maxAnswer = 0, ans; X = grid.size(); Y = grid[0].size(); for (unsigned i = 0; i < X; i++) { for (unsigned j = 0; j < Y; j++) { if (grid[i][j] == 1 && tag[i][j] == 0) { landNum++; search(grid, i, j); } } } /*define the direction*/ enum { UP = 0, RIGHT, DOWN, LEFT }; unsigned tagIsland[4]; unordered_map<unsigned,unsigned> count; for (unsigned i = 0; i < X; i++) { for (unsigned j = 0; j < Y; j++) { if (grid[i][j] == 0) { ans = 1; tagIsland[UP] = i >= 1 ? tag[i - 1][j] : 0; tagIsland[RIGHT] = j < Y - 1 ? tag[i][j + 1] : 0; tagIsland[DOWN] = i < X - 1 ? tag[i + 1][j] : 0; tagIsland[LEFT] = j >= 1 ? tag[i][j - 1] : 0; for (unsigned k = UP; k <= LEFT;k++){ if(count[tagIsland[k]]==0&&tagIsland[k]!=0){ ans += area[tagIsland[k]]; count[tagIsland[k]]=1; } } maxAnswer = max(ans, maxAnswer); count.clear(); } } } if(maxAnswer==0) return X * Y; return maxAnswer; } };
咱們首先經過search()函數對整個表進行回溯初始化,使全部單獨的陸地都被編號。
而後經過對每塊海洋填海後的總area進行判斷,保留最大面積maxAnswer
,即每次計算出新的area後都有
maxAnswer=area>maxAnswer?area:maxAnswer;
在最後return前,若是maxAnswer=0
則表示所有都是陸地,能夠用反證法驗證: 若是至少有一個海洋,maxAnswer
至少爲1。全是陸地的話只用return整片陸地的總面積便可,即X*Y。
至此,這道題的其中一種作法就完成了。