LeetCode in Kotlin

675. Cut Off Trees for Golf Event

Hard

You are asked to cut off all the trees in a forest for a golf event. The forest is represented as an m x n matrix. In this matrix:

In one step, you can walk in any of the four directions: north, east, south, and west. If you are standing in a cell with a tree, you can choose whether to cut it off.

You must cut off the trees in order from shortest to tallest. When you cut off a tree, the value at its cell becomes 1 (an empty cell).

Starting from the point (0, 0), return the minimum steps you need to walk to cut off all the trees. If you cannot cut off all the trees, return -1.

Note: The input is generated such that no two trees have the same height, and there is at least one tree needs to be cut off.

Example 1:

Input: forest = [[1,2,3],[0,0,4],[7,6,5]]

Output: 6

Explanation: Following the path above allows you to cut off the trees from shortest to tallest in 6 steps.

Example 2:

Input: forest = [[1,2,3],[0,0,0],[7,6,5]]

Output: -1

Explanation: The trees in the bottom row cannot be accessed as the middle row is blocked.

Example 3:

Input: forest = [[2,3,4],[0,0,5],[8,7,6]]

Output: 6

Explanation: You can follow the same path as Example 1 to cut off all the trees. Note that you can cut off the first tree at (0, 0) before making any steps.

Constraints:

Solution

import java.util.LinkedList
import java.util.Objects
import java.util.PriorityQueue
import java.util.Queue

class Solution {
    private var r = 0
    private var c = 0
    fun cutOffTree(forest: List<List<Int>>): Int {
        val pq = PriorityQueue<Int>()
        for (integers in forest) {
            for (v in integers) {
                if (v > 1) {
                    pq.add(v)
                }
            }
        }
        var steps = 0
        while (pq.isNotEmpty()) {
            val count = minSteps(forest, pq.poll())
            if (count == -1) {
                return -1
            }
            steps += count
        }
        return steps
    }

    private fun minSteps(forest: List<List<Int>>, target: Int): Int {
        var steps = 0
        val dirs = arrayOf(intArrayOf(0, 1), intArrayOf(0, -1), intArrayOf(1, 0), intArrayOf(-1, 0))
        val visited = Array(forest.size) {
            BooleanArray(
                forest[0].size
            )
        }
        val q: Queue<IntArray> = LinkedList()
        q.add(intArrayOf(r, c))
        visited[r][c] = true
        while (q.isNotEmpty()) {
            val qSize = q.size
            for (i in 0 until qSize) {
                val curr = q.poll()
                if (forest[Objects.requireNonNull(curr)[0]][curr[1]] == target) {
                    r = curr[0]
                    c = curr[1]
                    return steps
                }
                for (k in 0..3) {
                    val dir = dirs[k]
                    val nr = dir[0] + curr[0]
                    val nc = dir[1] + curr[1]
                    if (nr < 0 || nr == visited.size || nc < 0 || nc == visited[0].size ||
                        visited[nr][nc] || forest[nr][nc] == 0
                    ) {
                        continue
                    }
                    q.add(intArrayOf(nr, nc))
                    visited[nr][nc] = true
                }
            }
            steps++
        }
        return -1
    }
}