827. Making A Large Island

You are given an n x n binary matrix grid. You are allowed to change at most one 0 to be 1.

Return the size of the largest island in grid after applying this operation.

An island is a 4-directionally connected group of 1s.

 

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.

For each 1 in the grid, we paint all connected 1 with the next available color (2, 3, and so on). We also remember the size of the island we just painted with that color.

 

Then, we analyze all 0 in the grid, and sum sizes of connected islands (based on the island color). Note that the same island can connect to 0 more than once. The example below demonstrates this idea (the answer is highlighted):

 

 1 class Solution {
 2     public int largestIsland(int[][] grid) {
 3         Map<Integer, Integer> map = new HashMap<>(); //Key: color, Val: size of island painted of that color
 4         map.put(0, 0); //We won't paint island 0, hence make its size 0, we will use this value later   
 5         int n = grid.length; 
 6         int colorIndex = 2; //0 and 1 is already used in grid, hence we start colorIndex from 2 
 7         for (int i = 0; i < n; i++) {
 8             for (int j = 0; j < n; j++) {
 9                 if (grid[i][j] == 1) {
10                     int size = paint(grid, i, j, colorIndex);
11                     map.put(colorIndex, size);
12                     colorIndex++;
13                 }
14             }
15         }
16     
17         //If there is no island 0 from grid, res should be the size of islands of first color
18         //If there is no island 1 from grid, res should be 0 
19         int res = map.getOrDefault(2, 0); 
20         for (int i = 0; i < n; i++) {
21             for (int j = 0; j < n; j++) {
22                 if (grid[i][j] == 0) {
23                     //We use a set to avoid repeatly adding islands with the same color
24                     Set<Integer> set = new HashSet<>();
25                     //If current island is at the boundary, we add 0 to the set, whose value is 0 in the map
26                     set.add(i > 0 ? grid[i - 1][j] : 0);
27                     set.add(i < n - 1 ? grid[i + 1][j] : 0);
28                     set.add(j > 0 ? grid[i][j - 1] : 0);
29                     set.add(j < n - 1 ? grid[i][j + 1] : 0);
30                     
31                     int newSize = 1; //We need to count current island as well, hence we init newSize with 1
32                     for (int color : set) newSize += map.get(color);
33                     res = Math.max(res, newSize);
34                 }
35             }
36         }
37         return res;
38     }
39     
40     //Helper method to paint current island and all its connected neighbors
41     //Return the size of all painted islands at the end
42     private int paint(int[][] grid, int i, int j, int color) {
43         if (i < 0 || j < 0 || i >= grid.length || j >= grid[0].length || grid[i][j] != 1) return 0;
44         grid[i][j] = color;
45         return 1 + paint(grid, i + 1, j, color) + paint(grid, i - 1, j, color) + paint(grid, i, j + 1, color) + paint(grid, i, j - 1, color);
46     }
47 }

Reference: https://leetcode.com/problems/making-a-large-island/discuss/127015/C%2B%2B-with-picture-O(n*m)

posted @ 2021-04-07 12:49  北叶青藤  阅读(72)  评论(0编辑  收藏  举报