问题:
给定m*n的二维数组,由0和1构成。
1代表陆地,0代表海洋。
求在任意一个0的位置填上陆地 1,使得获得最大面积陆地,求这个陆地的面积。
Example 1: Input: grid = [[1,0],[0,1]] Output: 3 Explanation: Change one 0 to 1 and connect two 1s, then we get an island with area = 3. Example 2: Input: grid = [[1,1],[1,0]] Output: 4 Explanation: Change the 0 to 1 and make the island bigger, only one island with area = 4. Example 3: Input: grid = [[1,1],[1,1]] Output: 4 Explanation: Can't change any 0 to 1, only one island with area = 4. Constraints: n == grid.length n == grid[i].length 1 <= n <= 500 grid[i][j] is either 0 or 1.
解法:DFS
思想:
首先对该地图,进行陆地标记color
标记记号从2开始...
(为了区分已经存在的0和1)
只有该陆地为 1 的时候,才可以标记。
标记时,向四周扩展,直到遇到海洋。同时记录该陆地的面积。作为返回值。
⚠️ 注意:若该陆地为 0 (海洋),返回0。若该陆地超出边缘,也返回 0。
1 int getclr(int i, int j, vector<vector<int>>& grid) { 2 if(i<0 || j<0 || i>=n || j>=m) return 0; 3 else return grid[i][j]; 4 } 5 // mark color 6 // && return the size of this island 7 int markclr(int i, int j, int clr, vector<vector<int>>& grid) { 8 //we can only mark the cell whose color is 1. 9 if(getclr(i,j,grid)!=1) return 0; 10 grid[i][j] = clr; 11 //color the adjcent cell of (i,j) 12 return 1+markclr(i+1,j,clr,grid)+markclr(i,j+1,clr,grid)+ 13 markclr(i-1,j,clr,grid)+markclr(i,j-1,clr,grid); 14 }
标记结束后,尝试所有0的cell,
若0填上陆地后,得到由该点连接的各个陆地面积之和。
⚠️ 注意:由于0以外的陆地都是1,因此所有陆地的面积都可计算到。0和1一定相邻。
对于一个0cell,
四周被标记了多少个大陆,就有多少个color,使用set保存这些color,会滤掉重复的color(同一块大陆)
将不同color的大陆面积相加+自己 1=即为该cell连起来大陆的面积。
1 for(int i=0; i<n; i++) { 2 for(int j=0; j<m ; j++) { 3 if(grid[i][j]==0) { 4 //get adjcent island color of this cell. 5 //and get each size of color to Add. 6 unordered_set<int> adjclr = {getclr(i+1,j,grid), 7 getclr(i,j+1,grid), 8 getclr(i-1,j,grid), 9 getclr(i,j-1,grid)}; 10 //print_set(adjclr); 11 res = max(res, 1+accumulate(adjclr.begin(), adjclr.end(), 0, 12 [&](int a, int b){return a+sizes[b];})); 13 } 14 } 15 }
然后在所有0cell的计算结果中,选最大。
⚠️ 注意:当地图中全部为1,就有可能没有0cell。这时最大面积即为整个地图面积。
代码参考:
1 class Solution { 2 public: 3 // void print_set(unordered_set<int>& seta){ 4 // printf("{"); 5 // for(int i:seta) { 6 // printf("%d,", i); 7 // } 8 // printf("} "); 9 // } 10 11 int n,m; 12 //get color of cell(i,j), if (i,j)is invalid, return 0 13 //cause sizes's idx is from 0. there is no -1. 14 int getclr(int i, int j, vector<vector<int>>& grid) { 15 if(i<0 || j<0 || i>=n || j>=m) return 0; 16 else return grid[i][j]; 17 } 18 // mark color 19 // && return the size of this island 20 int markclr(int i, int j, int clr, vector<vector<int>>& grid) { 21 //we can only mark the cell whose color is 1. 22 if(getclr(i,j,grid)!=1) return 0; 23 grid[i][j] = clr; 24 //color the adjcent cell of (i,j) 25 return 1+markclr(i+1,j,clr,grid)+markclr(i,j+1,clr,grid)+ 26 markclr(i-1,j,clr,grid)+markclr(i,j-1,clr,grid); 27 } 28 //create a map(sizes) to save the size of each color island. 29 int largestIsland(vector<vector<int>>& grid) { 30 //color to mark the island from 2.(cause to distinguish from existed 0 and 1) 31 vector<int> sizes={0,0};//sizes[color]=size; from 2. 32 33 //initial every island with marking colors 34 n = grid.size(); 35 m = grid[0].size(); 36 for(int i=0; i<n; i++) { 37 for(int j=0; j<m ; j++) { 38 if(grid[i][j]==1) { 39 //mark color to the island including cell(i,j) 40 //and add this size of this island with color(sizes.size()) 41 sizes.push_back(markclr(i, j, sizes.size(), grid)); 42 //printf("sizes.back():%d ",sizes.back()); 43 } 44 } 45 } 46 47 //check every 0 cell 48 int res=0; 49 for(int i=0; i<n; i++) { 50 for(int j=0; j<m ; j++) { 51 if(grid[i][j]==0) { 52 //get adjcent island color of this cell. 53 //and get each size of color to Add. 54 unordered_set<int> adjclr = {getclr(i+1,j,grid), 55 getclr(i,j+1,grid), 56 getclr(i-1,j,grid), 57 getclr(i,j-1,grid)}; 58 //print_set(adjclr); 59 res = max(res, 1+accumulate(adjclr.begin(), adjclr.end(), 0, 60 [&](int a, int b){return a+sizes[b];})); 61 } 62 } 63 } 64 if(res==0) return m*n;//all cell is 1 65 else return res; 66 } 67 };