mirror of
https://github.com/trekhleb/javascript-algorithms.git
synced 2025-07-07 18:10:24 +08:00
Add top-down dynamic programming solution to Jump Game.
This commit is contained in:
@ -0,0 +1,17 @@
|
||||
import dpTopDownJumpGame from '../dpTopDownJumpGame';
|
||||
|
||||
describe('dpTopDownJumpGame', () => {
|
||||
it('should solve Jump Game problem in top-down dynamic programming manner', () => {
|
||||
expect(dpTopDownJumpGame([1, 0])).toBeTruthy();
|
||||
expect(dpTopDownJumpGame([100, 0])).toBeTruthy();
|
||||
expect(dpTopDownJumpGame([2, 3, 1, 1, 4])).toBeTruthy();
|
||||
expect(dpTopDownJumpGame([1, 1, 1, 1, 1])).toBeTruthy();
|
||||
expect(dpTopDownJumpGame([1, 1, 1, 10, 1])).toBeTruthy();
|
||||
expect(dpTopDownJumpGame([1, 5, 2, 1, 0, 2, 0])).toBeTruthy();
|
||||
|
||||
expect(dpTopDownJumpGame([1, 0, 1])).toBeFalsy();
|
||||
expect(dpTopDownJumpGame([3, 2, 1, 0, 4])).toBeFalsy();
|
||||
expect(dpTopDownJumpGame([0, 0, 0, 0, 0])).toBeFalsy();
|
||||
expect(dpTopDownJumpGame([5, 4, 3, 2, 1, 0, 0])).toBeFalsy();
|
||||
});
|
||||
});
|
78
src/algorithms/uncategorized/jump-game/dpTopDownJumpGame.js
Normal file
78
src/algorithms/uncategorized/jump-game/dpTopDownJumpGame.js
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* DYNAMIC PROGRAMMING TOP-DOWN approach of solving Jump Game.
|
||||
*
|
||||
* This comes out as an optimisation of BACKTRACKING approach.
|
||||
* Optimisation is done by using memo table where we store information
|
||||
* about each cell whether it is "good" or "bad" or "unknown".
|
||||
*
|
||||
* We call a position in the array a "good" one if starting at that
|
||||
* position, we can reach the last index.
|
||||
*
|
||||
* @param {number[]} numbers - array of possible jump length.
|
||||
* @param {number} startIndex - index from where we start jumping.
|
||||
* @param {number[]} currentJumps - current jumps path.
|
||||
* @param {boolean[]} cellsGoodness - holds information about whether cell is "good" or "bad"
|
||||
* @return {boolean}
|
||||
*/
|
||||
export default function dpTopDownJumpGame(
|
||||
numbers,
|
||||
startIndex = 0,
|
||||
currentJumps = [],
|
||||
cellsGoodness = [],
|
||||
) {
|
||||
if (startIndex === numbers.length - 1) {
|
||||
// We've jumped directly to last cell. This situation is a solution.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Init cell goodness table if it is empty.
|
||||
// This is DYNAMIC PROGRAMMING feature.
|
||||
const currentCellsGoodness = [...cellsGoodness];
|
||||
if (!currentCellsGoodness.length) {
|
||||
numbers.forEach(() => currentCellsGoodness.push(undefined));
|
||||
// Mark the last cell as "good" one since it is where
|
||||
// we ultimately want to get.
|
||||
currentCellsGoodness[cellsGoodness.length - 1] = true;
|
||||
}
|
||||
|
||||
// Check what the longest jump we could make from current position.
|
||||
// We don't need to jump beyond the array.
|
||||
const maxJumpLength = Math.min(
|
||||
numbers[startIndex], // Jump is within array.
|
||||
numbers.length - 1 - startIndex, // Jump goes beyond array.
|
||||
);
|
||||
|
||||
// Let's start jumping from startIndex and see whether any
|
||||
// jump is successful and has reached the end of the array.
|
||||
for (let jumpLength = maxJumpLength; jumpLength > 0; jumpLength -= 1) {
|
||||
// Try next jump.
|
||||
const nextIndex = startIndex + jumpLength;
|
||||
|
||||
// Jump only into "good" or "unknown" cells.
|
||||
// This is top-down dynamic programming optimisation of backtracking algorithm.
|
||||
if (currentCellsGoodness[nextIndex] !== false) {
|
||||
currentJumps.push(nextIndex);
|
||||
|
||||
const isJumpSuccessful = dpTopDownJumpGame(
|
||||
numbers,
|
||||
nextIndex,
|
||||
currentJumps,
|
||||
currentCellsGoodness,
|
||||
);
|
||||
|
||||
// Check if current jump was successful.
|
||||
if (isJumpSuccessful) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// BACKTRACKING.
|
||||
// If previous jump wasn't successful then retreat and try the next one.
|
||||
currentJumps.pop();
|
||||
|
||||
// Mark current cell as "bad" to avoid its deep visiting later.
|
||||
currentCellsGoodness[nextIndex] = false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
Reference in New Issue
Block a user