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
.
解题思路:
很明显的Union Find的题目。先求1的连通块 ;
然后再依次求将0变成1后的最大连通块 ;
时间复杂度为O(2*M*N*4);
时间复杂度还是比较高的,再看看怎么改进
class Solution {
public:
int largestIsland(vector<vector<int>>& grid)
{
int m = grid.size() , n = grid[0].size() ;
root = vector<int>(m * n , - 1) ;
unordered_map<int , unordered_set<int>> islands ;
int max_area = 0 , cnt_0 = 0 ;
for(int i = 0 ; i < m ; ++i)
{
for(int j = 0 ; j < n ; ++j)
{
if(grid[i][j] == 0)
{
cnt_0++ ;
continue ;
}
int r = find(i * n + j) ;
islands[r].insert(i * n + j) ;
for(int k = 0 ; k < 4 ; ++k)
{
int new_i = i + dir[k] , new_j = j + dir[k + 1] ;
if(new_i < 0 || new_i >= m || new_j < 0 || new_j >= n || grid[new_i][new_j] == 0) continue ;
r = merge(r , new_i * n + new_j , islands) ;
}
max_area = max(max_area , (int)islands[r].size()) ;
}
}
if(cnt_0 == 0) return max_area ;
for(int i = 0 ; i < m ; ++i)
{
for(int j = 0 ; j < n ; ++j)
{
if(grid[i][j] == 1) continue ;
max_area = max(max_area , change(i * n + j , grid , islands)) ;
}
}
return max_area ;
}
int find(int i)
{
return root[i] == -1 ? i : find(root[i]) ;
}
int merge(int i , int j , unordered_map<int , unordered_set<int>> &islands)
{
int x = find(i) , y = find(j) ;
islands[x].insert(i) ;
islands[y].insert(j) ;
if(x < y)
{
root[y] = x ;
islands[x].insert(islands[y].begin() , islands[y].end()) ;
islands.erase(y) ;
return x ;
}
else if(x > y)
{
root[x] = y ;
islands[y].insert(islands[x].begin() , islands[x].end()) ;
islands.erase(x) ;
return y ;
}
else return x ;
}
int change(int x , vector<vector<int>>& grid , unordered_map<int , unordered_set<int>>& islands)
{
int m = grid.size() , n = grid[0].size() ;
int i = x / n , j = x % n ;
unordered_set<int> island{x};
int ro = find(x) ;
for(int k = 0 ; k < 4 ; ++k)
{
int new_i = i + dir[k] , new_j = j + dir[k + 1] ;
if(new_i < 0 || new_i >= m || new_j < 0 || new_j >= n || grid[new_i][new_j] == 0) continue ;
int r = find(new_i * n + new_j ) ;
if(ro != r)
{
island.insert(islands[r].begin() , islands[r].end()) ;
ro = r ;
}
}
return island.size() ;
}
private:
vector<int> root , dir = {-1 , 0 , 1 , 0 , -1};
};