Skip to content

Latest commit

 

History

History
124 lines (111 loc) · 3.38 KB

827.making-a-large-island.md

File metadata and controls

124 lines (111 loc) · 3.38 KB

Traversal

1 1 0 0 0
1 1 0 0 0
0 0 1 0 0
1 1 0 1 1
0 0 1 0 0
0 0 1 0 0

We calculate the area of each island and store it in a dictionary. (In our implementation, we change the cell to an index.)

flood-fill algorithm!!

A A 0 0 0   A: 4
A A 0 0 0   B: 1
0 0 B 0 0   C: 2
C C 0 D D   D: 2
0 0 E 0 0   E: 2
0 0 E 0 0

Then we traverse the grid and for each 0's cell, we flip it to 1's and calculate the area of the island that it connects to by checking the 4 directions adjacent area. We sum the areas of the islands that it connects to.

A A _  //                A   B
A A 1  // new area = 1 + 4 + 1 = 6 
_ _ B

_ _ B _ _  //                B   C   D   E
C C 1 D D  // new area = 1 + 1 + 2 + 2 + 2
_ _ E _ _
_ _ E _ _

But we have to avoid duplicate connecting. We can use a set to filter out what we have connected.

A A _        A
A 1 _  =>  A 1  // duplicate
A A _        A  // duplicate
class Solution {
    private val directions = arrayOf(
        intArrayOf(-1, 0),
        intArrayOf(1, 0),
        intArrayOf(0, -1),
        intArrayOf(0, 1)
    )

    fun largestIsland(grid: Array<IntArray>): Int {
        val m = grid.size
        val n = grid[0].size
        var index = 2
        val areaMapping = HashMap<Int, Int>()
        for (i in 0 until m) {
            for (j in 0 until n) {
                if (grid[i][j] == 1) {
                    val area = dfs(grid, i, j, index)
                    areaMapping[index] = area
                    index++
                }
            }
        }

        /*
        A A 0 0 0   A: 4
        A A 0 0 0   B: 1
        0 0 B 0 0   C: 2
        C C 0 D D   D: 2
        0 0 E 0 0   E: 2
        0 0 E 0 0
         */

        var maxArea = 0
        for (i in 0 until m) {
            for (j in 0 until n) {
                if (grid[i][j] == 0) {
                    var area = 1
                    // We track which area is connected
                    var addedIndex = HashSet<Int>()
                    directions.forEach { d ->
                        val newX = i + d[0]
                        val newY = j + d[1]
                        if (newX in 0 until m && newY in 0 until n) {
                            val cell = grid[newX][newY]
                            if (!addedIndex.contains(cell)) {
                                addedIndex.add(cell)
                                area += (areaMapping[cell] ?: 0)
                            }
                        }
                    }
                    maxArea = maxOf(maxArea, area)
                } else {
                    maxArea = maxOf(maxArea, areaMapping[grid[i][j]] ?: 0)
                }
            }
        }
        return maxArea
    }

    // DFS to calculate the area, and mark the cell to `index`
    private fun dfs(grid: Array<IntArray>, x: Int, y: Int, index: Int): Int {
        val m = grid.size
        val n = grid[0].size
        if (x !in 0 until m || y !in 0 until n) return 0
        if (grid[x][y] == index || grid[x][y] == 0) return 0

        grid[x][y] = index
        var area = 1
        directions.forEach { d -> 
            val newX = x + d[0]
            val newY = y + d[1]
            area += dfs(grid, newX, newY, index)
        }
        return area
    }
}
  • Time Complexity: O(n^2)
  • Space Complexity: O(n^2)