给你一个大小为 n x n 二进制矩阵 grid 。最多 只能将一格 0 变成 1 。
返回执行此操作后,grid 中最大的岛屿面积是多少?
岛屿 由一组上、下、左、右四个方向相连的 1 形成。
示例 1:
输入: grid = [[1, 0], [0, 1]] 输出: 3 解释: 将一格0变成1,最终连通两个小岛得到面积为 3 的岛屿。
示例 2:
输入: grid = [[1, 1], [1, 0]] 输出: 4 解释: 将一格0变成1,岛屿的面积扩大为 4。
思路:首先求未变化前的grid的最大岛屿面积(相邻格为1的最大格子数)方法可以是(从grid[0][0]位置开始用深度优先遍历找相邻为1的格子数量),遍历变化某一格后的grid最大岛屿面积,并保存最大值返回
class Solution {
public:
//找到该grid最大岛屿数
int find_max(vector<vector<int>> grid)
{
int ret=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid.size();j++)
{
int temp=0;
if(grid[i][j]==0) continue;
//该点可以当岛屿
vector<vector<int>> temp_grid(grid);
queue<pair<int,int>> q;
q.push(make_pair(i,j));
//设置i,j该点已经走过了
temp_grid[i][j]=0;
temp++;
while(!q.empty())
{
//找4个方向是否有1且未插入
pair<int,int> k=q.front();
q.pop();
if(k.first+1<grid.size()&&temp_grid[k.first+1][k.second]==1)
{
q.push(make_pair(k.first+1,k.second));
temp_grid[k.first+1][k.second]=0;
temp++;
}
if(k.first-1>=0&&temp_grid[k.first-1][k.second]==1)
{
q.push(make_pair(k.first-1,k.second));
temp_grid[k.first-1][k.second]=0;
temp++;
}
if(k.second+1<grid.size()&&temp_grid[k.first][k.second+1]==1)
{
q.push(make_pair(k.first,k.second+1));
temp_grid[k.first][k.second+1]=0;
temp++;
}
if(k.second-1>=0&&temp_grid[k.first][k.second-1]==1)
{
q.push(make_pair(k.first,k.second-1));
temp_grid[k.first][k.second-1]=0;
temp++;
}
}
ret=max(ret,temp);
}
}
return ret;
}
int largestIsland(vector<vector<int>>& grid) {
int ret=0;
//找到元素为0的下标
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid.size();j++)
{
vector<vector<int>> temp(grid);
temp[i][j]=1;
ret=max(find_max(temp),ret);
}
}
return ret;
}
};
但该方法因时间效率过高,会超出时间限制
优化思路:
1.对原始地图进行一次深搜,将不同的岛屿标记为不同的编号。
2.用哈希表记录每个编号对应的“岛屿”的面积,key为编号,val为面积。
3.之后再遍历一遍地图,如果某个小方格为0,就尝试把这个方格填平。并求出修改后对应岛屿面积=1(自己)+上下左右可能含有的编号对应面积
class Solution {
public:
int largestIsland(vector<vector<int>>& grid) {
int ret=1;
unordered_map<int,int> m;
//编号为0即面积为0
m[0]=0;
int num=1;
vector<vector<int>> temp_grid(grid);
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid.size();j++)
{
//不是新岛屿重找
if(temp_grid[i][j]!=1) continue;
int temp=0;
//新岛屿新编号
num++;
queue<pair<int,int>> q;
q.push(make_pair(i,j));
//设置i,j该点已经走过了
temp_grid[i][j]=num;
temp++;
while(!q.empty())
{
//找4个方向是否有1
pair<int,int> k=q.front();
q.pop();
if(k.first+1<grid.size()&&temp_grid[k.first+1][k.second]==1)
{
q.push(make_pair(k.first+1,k.second));
temp_grid[k.first+1][k.second]=num;
temp++;
}
if(k.first-1>=0&&temp_grid[k.first-1][k.second]==1)
{
q.push(make_pair(k.first-1,k.second));
temp_grid[k.first-1][k.second]=num;
temp++;
}
if(k.second+1<grid.size()&&temp_grid[k.first][k.second+1]==1)
{
q.push(make_pair(k.first,k.second+1));
temp_grid[k.first][k.second+1]=num;
temp++;
}
if(k.second-1>=0&&temp_grid[k.first][k.second-1]==1)
{
q.push(make_pair(k.first,k.second-1));
temp_grid[k.first][k.second-1]=num;
temp++;
}
}
m[num]=temp;
}
}
if(num==1) return 1;
//找到元素为0的下标
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid.size();j++)
{
int temp=m[temp_grid[i][j]];
if(grid[i][j]==0)
{
temp++;
//上下左右岛屿面积相加(需去重复的编号)
unordered_set<int> s;
if(i+1<grid.size()&&temp_grid[i+1][j]!=0) s.insert(temp_grid[i+1][j]);
if(i-1>=0&&temp_grid[i-1][j]!=0) s.insert(temp_grid[i-1][j]);
if(j+1<grid.size()&&temp_grid[i][j+1]!=0) s.insert(temp_grid[i][j+1]);
if(j-1>=0&&temp_grid[i][j-1]!=0) s.insert(temp_grid[i][j-1]);
for(int e:s)
{
temp+=m[e];
}
}
ret=max(ret,temp);
}
}
return ret;
}
};