subject
Give you a binary matrix grid of size m x n.
An island is a combination of some adjacent 1s (representing land). The "adjacent" here requires that two 1s must be adjacent in four horizontal or vertical directions. You can assume that the four edges of the grid are surrounded by 0 (representing water).
The area of an island is the number of cells on the island with a value of 1.
Calculate and return the largest island area in the grid. If there are no islands, the return area is 0.
Example 1:
Input: grid = [[0,0,1,0,0,0,0,1,0,0,0,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,1,1,0,1,0,0,0,0,0,0,0,0],[0,1,0,0,1,1,0,0,1,0,1,0,0],[0,1,0,0,1,1,0,0,1,1,1,0,0],[0,0,0,0,0,0,0,0,0,0,1,0,0],[0,0,0,0,0,0,0,1,1,1,0,0,0],[0,0,0,0,0,0,0,1,1,0,0,0,0]] Output: 6 Explanation: the answer should not be 11, because the island can only contain 1 in the horizontal or vertical directions.
Example 2:
Input: grid = [[0,0,0,0,0,0,0,0]] Output: 0
Tips:
- m = = g r i d . l e n g t h m == grid.length m==grid.length
- n = = g r i d [ i ] . l e n g t h n == grid[i].length n==grid[i].length
- 1 < = m , n < = 50 1 <= m, n <= 50 1<=m,n<=50
- g r i d [ i ] [ j ] by 0 or 1 grid[i][j] is 0 or 1 grid[i][j] is 0 or 1
Problem solution
Solution 1: depth first search
[ideas]
We want to know the area of each connected shape in the grid, and then take the maximum value.
If we explore each land connected to it (and the land connected to these lands) in four directions on a land, the total number of lands explored will be the area of the connected shape.
In order to ensure that each land is visited no more than once, we set the value of this land to 0 every time we pass through a land. So we won't visit the same land many times
[Code]
class Solution { public: //DFS int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; int m, n; int dfs(vector<vector<int>> &grid, int x, int y) { int ans = 1; grid[x][y] = 0; //The accessed is marked as 0 to prevent access again for (int i = 0; i < 4; i++) { int xx = x + dir[i][0]; int yy = y + dir[i][1]; if (xx < 0 || xx >= m || yy < 0 || yy >= n || grid[xx][yy] == 0) continue ; ans += dfs(grid, xx, yy); } return ans; } int maxAreaOfIsland(vector<vector<int>>& grid) { m = grid.size(); n = grid[0].size(); int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1) { ans = max(ans, dfs(grid, i, j)); } } } return ans; } };
[complexity analysis]
- Time complexity: O ( R × C ) O(R \times C) O(R × C). among R R R is the number of rows in a given grid, C C C is the number of columns. We visit each grid at most once.
- Space complexity: O ( R × C ) O(R \times C) O(R × C) , the depth of recursion is most likely the size of the entire mesh, so it is most likely to use O ( R × C ) O(R \times C) O(R × C) Stack space.
Solution 2: depth first search + stack
[ideas]
You can use the stack to implement the depth first search algorithm. This method is essentially the same as method I, with the only difference being:
Method 1 indicates which land you want to traverse next through function calls, and allows the next layer of functions to access these lands. The second method puts the land you want to traverse next in the stack, and then accesses them when you take out these lands.
When visiting each piece of land, we will explore the four directions around it, find the land that has not been visited and add it to the stack;
In addition, as long as the stack is not empty, it means that we still have land to access. Then take an element from the stack and access it.
[Code]
class Solution { public: //DFS + stack int maxAreaOfIsland(vector<vector<int>>& grid) { int m = grid.size(); int n = grid[0].size(); int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; stack<pair<int, int>> sta; int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { int len = 0; sta.push({i, j}); while (!sta.empty()) { int x = sta.top().first; int y = sta.top().second; sta.pop(); if (x < 0 || y < 0 || x >= m || y >= n || grid[x][y] == 0) continue; len++; grid[x][y] = 0; for (int i = 0; i < 4; i++) { int xx = x + dir[i][0]; int yy = y + dir[i][1]; sta.push({xx, yy}); } } ans = max(ans, len); } } return ans; } };
[complexity analysis]
- Time complexity: O ( R × C ) O(R \times C) O(R × C). among R R R is the number of rows in a given grid, C C C is the number of columns. We visit each grid at most once.
- Space complexity: O ( R × C ) O(R \times C) O(R × C) , the stack can store all lands at most, and the maximum number of lands is R × C R \times C R × C block, so the space used is O ( R × C ) O(R \times C) O(R×C).
Solution 3: breadth first search
[ideas]
Change the stack in method 2 into a queue, take out the land from the head of the team every time, and put the land you want to traverse at the end of the team to realize the breadth first search algorithm.
[Code]
class Solution { public: //BFS int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1}; int maxAreaOfIsland(vector<vector<int>>& grid) { int m = grid.size(); int n = grid[0].size(); queue<pair<int, int>> que; int ans = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { if (grid[i][j] == 1) { grid[i][j] = 0; que.push({i, j}); int len = 1; while (!que.empty()) { int x = que.front().first; int y = que.front().second; que.pop(); for (int i = 0; i < 4; i++) { int nx = x + dir[i][0]; int ny = y + dir[i][1]; if (nx < 0 || nx >= m || ny < 0 || ny >= n || grid[nx][ny] == 0) continue; grid[nx][ny] = 0; len++; que.push({nx, ny}); } } ans = max(ans, len); } } } return ans; } };
[complexity analysis]
- Time complexity: O ( R × C ) O(R \times C) O(R × C). among R R R is the number of rows in a given grid, C C C is the number of columns. We visit each grid at most once.
- Space complexity: O ( R × C ) O(R \times C) O(R × C) , the queue will store up to all land, and the maximum number of land is R × C R \times C R × C block, so the space used is O ( R × C ) O(R \times C) O(R×C).
Solution 4: joint search set
[ideas]
Put the adjacent ones into the same set, and the required result is the maximum number of branches in the set.
[Code]
class Solution { private: void init(int n) { parent.resize(n); rank.resize(n); for (int i = 0; i < n; i++) { parent[i] = i; rank[i] = 1; } } int find(int x) { return parent[x] == x ? x : parent[x] = find(parent[x]); } bool isConnected(int u, int v) { return find(u) == find(v); } void merge(int u, int v) { int pu = find(u), pv = find(v); if (pu == pv) return ; if (rank[pu] < rank[pv]) { parent[pu] = pv; rank[pv] += rank[pu]; } else { parent[pv] = pu; rank[pu] += rank[pv]; } } int getMaxRank() { for (int i = 0; i < rank.size(); i++) ans = max(ans, rank[i]); return ans; } int ans = 0; vector<int> rank; //Number of branches in each connected component vector<int> parent;//Root node of each branch public: //Two dimensional to one dimensional int maxAreaOfIsland(vector<vector<int>>& grid) { int m = grid.size(); if (m == 0) return 0; int n = grid[0].size(); init(m * n); bool existLand = false; for (int row = 0; row < m; row++) { for (int col = 0; col < n; col++) { int ind = row * n + col; if (grid[row][col] == 1) { existLand = true; //2D to 1D column to column if (row > 0 && grid[row - 1][col] == 1) merge(ind, (row - 1) * n + col); if (col > 0 && grid[row][col - 1] == 1) merge(ind, row * n + col - 1); } } } if (!existLand) return 0; return getMaxRank(); } };
[complexity analysis]
- Time complexity: O ( m × n ) O(m \times n) O(m × n) , where m m m is the number of rows of the grid, n n n is the number of columns in the grid.
- Space complexity: O ( m × n ) O(m \times n) O(m × n) And look up the space required by the set.