675. Cut Off Trees for Golf Event
Description
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:
0
means the cell cannot be walked through.1
represents an empty cell that can be walked through.- A number greater than
1
represents a tree in a cell that can be walked through, and this number is the tree's height.
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:
m == forest.length
n == forest[i].length
1 <= m, n <= 50
0 <= forest[i][j] <= 109
- Heights of all trees are distinct.
Solutions
Solution: Breadth-First Search
- Time complexity: O(m2n2)
- Space complexity: O(mn)
JavaScript
/**
* @param {number[][]} forest
* @return {number}
*/
const cutOffTree = function (forest) {
if (!forest[0][0]) return -1;
const m = forest.length;
const n = forest[0].length;
const trees = [];
for (let row = 0; row < m; row++) {
for (let col = 0; col < n; col++) {
const height = forest[row][col];
if (height <= 1) continue;
trees.push({ row, col, height });
}
}
trees.sort((a, b) => a.height - b.height);
const directions = [
[0, -1],
[0, 1],
[-1, 0],
[1, 0],
];
let current = [0, 0];
let result = 0;
const getMoveStep = (start, destination) => {
const visited = new Array(m)
.fill('')
.map(_ => new Array(n).fill(false));
let queue = [start];
let steps = 0;
visited[start[0]][start[1]] = true;
while (queue.length) {
const size = queue.length;
const nextQueue = [];
for (let index = 0; index < size; index++) {
const [row, col] = queue[index];
if (row === destination.row && col === destination.col) return steps;
for (const [moveRow, moveCol] of directions) {
const nextRow = row + moveRow;
const nextCol = col + moveCol;
if (nextRow < 0 || nextCol < 0 || nextRow >= m || nextCol >= n) continue;
if (!forest[nextRow][nextCol]) continue;
if (visited[nextRow][nextCol]) continue;
nextQueue.push([nextRow, nextCol]);
visited[nextRow][nextCol] = true;
}
}
queue = nextQueue;
steps += 1;
}
return -1;
};
for (const { row, col } of trees) {
const steps = getMoveStep(current, { row, col });
if (steps === -1) return -1;
current = [row, col];
result += steps;
}
return result;
};