Given an array of integers arr
, you are initially positioned at the first index of the array.
In one step you can jump from index i
to index:
i + 1
where:i + 1 < arr.length
.i - 1
where:i - 1 >= 0
.j
where:arr[i] == arr[j]
andi != j
.
Return the minimum number of steps to reach the last index of the array.
Notice that you can not jump outside of the array at any time.
Example
Input: arr = [100,-23,-23,404,100,23,23,23,3,404]
Output: 3
Explanation: You need three jumps from index 0 --> 4 --> 3 --> 9. Note that index 9 is the last index of the array.
Solution
Great solution found here.
/**
* @param {number[]} arr
* @return {number}
*/
var minJumps = function (arr) {
// build a map of value to indexes
const targetIndex = arr.length - 1;
if (targetIndex < 1) return 0;
const map = new Map();
for (let i = 0; i < arr.length; i++) {
// if (i == targetIndex) continue;
if (!map.has(arr[i])) map.set(arr[i], []);
map.get(arr[i]).push(i);
}
// start from the end. check if the value is the same as the target. if so, return 1
let checkedIndexes = new Set();
let stepCount = 0;
let currentStepIndexes = new Set();
currentStepIndexes.add(targetIndex);
// from right to left. end to start. arr.length - 1 to 0
while (currentStepIndexes.size > 0) {
let nextStepIndexes = new Set();
for (const currentStepIndex of currentStepIndexes.values()) {
checkedIndexes.add(currentStepIndex);
if (currentStepIndex == 0) return stepCount;
// -1
if (currentStepIndex > 0 && !checkedIndexes.has(currentStepIndex - 1)) {
if (currentStepIndex - 1 == 0) return ++stepCount;
nextStepIndexes.add(currentStepIndex - 1);
}
// jumps
const jumps = map.get(arr[currentStepIndex]);
if (jumps) {
map.delete(arr[currentStepIndex]);
let limit = 0;
for (const jumpIndex of jumps) {
// if (jumpIndex == targetIndex) return ++stepCount;
if (
jumpIndex !== currentStepIndex &&
!checkedIndexes.has(jumpIndex)
) {
limit++;
if (limit > 5) break;
if (jumpIndex == 0) return ++stepCount;
nextStepIndexes.add(jumpIndex);
}
}
}
// +1
if (
currentStepIndex < targetIndex &&
!checkedIndexes.has(currentStepIndex + 1)
) {
nextStepIndexes.add(currentStepIndex + 1);
}
}
currentStepIndexes = nextStepIndexes;
stepCount++;
}
return stepCount;
};