https://leetcode.com/problems/making-a-large-island/
In a 2D grid of 0
s and 1
s, we change at most one 0
to a 1
.
After, what is the size of the largest island? (An island is a 4-directionally connected group of 1
s).
Example 1:
Input: [[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: [[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: [[1, 1], [1, 1]] Output: 4 Explanation: Can't change any 0 to 1, only one island with area = 4.
Notes:
-
1 <= grid.length = grid[0].length <= 50
. -
0 <= grid[i][j] <= 1
.
题目分析:在一个2D地图中,将其中一个0变成1,那么岛屿最大的大小是多少。
算法思路:首先就想到dfs,遍历地图,将其中一个0变成1,然后进行dfs,用res来保存结果,不过要注意地图全是1的情况,故而用一个布尔变量hasZero进行控制。
对于第一种做法,存在大量的重复dfs,在第二种方法中针对dfs进行改进,只要有一个岛连通(一个连通分量),我们就用index来标记,并将该index对应的个数记录在area向量中,然后再次遍历一个地图,针对每一个0,找到四个方向的标记是否>1,是的话,将其加入unordered_set<int> us中(可以进行index去重)。注:index从2开始,以示区分grid中的0、1,好处就是可以不需要visited向量就可以知道某个点是否访问过,避免重复访问。
//dfs O(n^4) O(n^2)
//Runtime: 1184 ms, faster than 5.02% of C++ online submissions for Making A Large Island.
//Memory Usage: 97.4 MB, less than 11.11% of C++ online submissions for Making A Large Island.
class Solution {
public:
int largestIsland(vector<vector<int>>& grid) {
int m=grid.size(),n=grid[0].size(),res=0;
bool hasZero=false;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1) continue;
grid[i][j]=1;
vector<vector<bool>> visited(m,vector<bool>(n,false));
res=max(res,dfs(grid,visited,i,j));
grid[i][j]=0;
if(res==m*n) return res;
hasZero=true;
}
}
return hasZero ? res : m*n;
}
private:
int dfs(vector<vector<int>>& grid,vector<vector<bool>>& visited,int i, int j){
int m=grid.size(),n=grid[0].size();
if(i<0 || i>=m || j<0 || j>=n || grid[i][j]==0 || visited[i][j]) return 0;
visited[i][j]=true;
return 1+dfs(grid,visited,i,j-1)+dfs(grid,visited,i-1,j)
+dfs(grid,visited,i,j+1)+dfs(grid,visited,i+1,j);
}
};
//O(n^2) O(n^2)
//Runtime: 16 ms, faster than 90.67% of C++ online submissions for Making A Large Island.
//Memory Usage: 12.3 MB, less than 100.00% of C++ online submissions for Making A Large Island.
class Solution {
public:
int largestIsland(vector<vector<int>>& grid) {
int m=grid.size(),n=grid[0].size(),res=0;
vector<int> area(m*n+2,0);
int index=2;
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==1){
area[index]=dfs(grid,i,j,index);
index++;
}
}
}
for(auto x : area) res=max(res,x);
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
if(grid[i][j]==0){
unordered_set<int> us;
neighbors(grid,us,i,j);
int ans=1;
for(auto index : us) ans+=area[index];
res=max(res,ans);
}
}
}
return res;
}
private:
int dx[4]={0,-1,0,1};
int dy[4]={-1,0,1,0};
bool isValid(const int& m,const int& n,const int& i,const int& j){
if(i<0 || i>=m || j<0 || j>=n) return false;
return true;
}
int dfs(vector<vector<int>>& grid,int i, int j,int index){
int m=grid.size(),n=grid[0].size();
if(!isValid(m,n,i,j) || grid[i][j]!=1) return 0;
grid[i][j]=index;
return 1+dfs(grid,i,j-1,index)+dfs(grid,i-1,j,index)
+dfs(grid,i,j+1,index)+dfs(grid,i+1,j,index);
}
void neighbors(vector<vector<int>>& grid,unordered_set<int>& us,int i,int j){
int m=grid.size(),n=grid[0].size();
for(int k=0;k<4;k++){
int x=i+dx[k];
int y=j+dy[k];
if(isValid(m,n,x,y) && grid[x][y]>1)
us.insert(grid[x][y]);
}
}
};