Created
January 23, 2020 23:07
-
-
Save crates/567139a108305fdd1c182ec8dfcdb506 to your computer and use it in GitHub Desktop.
What's the fastest way to cut down trees for a golf tournament? (LeetCode problem)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Designed to solve this LeetCode problem: https://leetcode.com/problems/cut-off-trees-for-golf-event/ | |
// Author: Crates McD (https://cr8s.net) | |
// Runtime: 3912 ms, faster than 18.95% of JavaScript online submissions for Cut Off Trees for Golf Event. | |
// Memory Usage: 51.8 MB, less than 100.00% of JavaScript online submissions for Cut Off Trees for Golf Event. | |
/** | |
* @param {number[][]} forest | |
* @return {number} | |
*/ | |
const cutOffTree = (forest) => { | |
const deforest = {}; | |
for (let i = 0; i < forest.length; i++) { | |
for (let j = 0; j < forest[0].length; j++) { | |
let value = forest[i][j]; | |
if (value > 1) deforest[value] = [i, j]; | |
} | |
} | |
deforest[1] = [0, 0]; // this represents the start of the matrix for deforestation; the first tree to cut | |
const treeHeights = Object.keys(deforest).sort((a, b) => parseInt(a) - parseInt(b)); | |
let steps = 0; | |
let blocked = false; | |
let done = false; | |
while (!blocked && !done) { | |
let start = deforest[treeHeights.shift()]; | |
let finish; | |
if (!treeHeights.length) { | |
done = true; | |
break; | |
} | |
finish = deforest[ treeHeights[0] ]; | |
const nextSteps = getSteps(start, finish, forest); | |
if (nextSteps === -1) { | |
blocked = true; | |
break; | |
} else steps += nextSteps; | |
} | |
if (blocked) return -1; | |
return steps; | |
}; | |
/** | |
* Breadth first search (BFS) function to calculate number of steps between coordinates in the array matrix | |
* also checks if a route is possible given previously visited coordinates and obstacles (represented as value 0 in the matrix) | |
* @param {[]number(2) like [i,j]} start | |
* @param {[]number(2) like [i,j]} finish | |
* @param {[][]} forest | |
* @return {number} | |
*/ | |
const getSteps = (start, finish, forest) => { | |
const matrix = JSON.parse(JSON.stringify(forest)); // deep clone the matrix | |
const visited = []; | |
let queue = [start]; | |
let nextQueue = []; | |
let found = false; | |
let blocked = false; | |
let steps = 0; | |
while (!found && !blocked) { | |
if (!queue.length && nextQueue.length) { | |
queue = nextQueue; | |
nextQueue = []; | |
steps = steps + 1; | |
} | |
const cur = queue.shift(); | |
const thisValue = matrix[cur[0]][cur[1]]; | |
if (cur[0] === finish[0] && cur[1] === finish[1]) | |
found = true; | |
else if (thisValue > 0) { // check surrounding coordinates on next step: | |
if (cur[1] > 0) | |
nextQueue.push([cur[0], cur[1] - 1 ]); | |
if (cur[0] > 0) | |
nextQueue.push([cur[0] - 1, cur[1]]); | |
if (cur[0] < matrix.length - 1) | |
nextQueue.push([cur[0] + 1, cur[1]]); | |
if (cur[1] < matrix[0].length - 1) | |
nextQueue.push([cur[0], cur[1] + 1]); | |
matrix[cur[0]][cur[1]] = -1; | |
} else if(!queue.length && !nextQueue.length) blocked = true; | |
} | |
if (blocked) return -1; | |
return steps; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment