题目
- 从 0 位置出发,每个位置都可能去往多个位置,记录下一层的位置,来到下一层时步数+1,遍历下一层查看是否抵达最后一个位置,如果抵达返回步数,如果没有继续记录一下层的所有位置,然后来到下一层
- 比常规的宽度优先遍历多了一个记录下一层终止位置的步骤,通过决策下一步能来到的所有位置,查看是否满足条件
function process(arr) {
const map = new Map();
// 记录某个元素出现的所有位置
for (let i = 0; i <= arr.length; i++) {
if (!map.get(arr[i])) {
map.set(arr[i], [i]);
} else {
map.set(arr[i], map.get(arr[i]).push(i));
}
}
// 已经抵达的位置不需要继续遍历,因为步骤一定比之前的多
const visited = Array(arr.length).fill(false);
const queue = Array(arr.length);
let left = 0,
right = 0;
// 把 0 位置加到队列,从0开始宽度优先遍历
queue[right++] = 0;
visited[0] = true;
let jump = 0;
while (left !== right) {
// 记录当前层的终止位置
let temp = right;
// 遍历当前层
for (; left < temp; left++) {
let current = queue[left];
// 如果来到了数组最后一个位置
if (current === arr.length - 1) {
return jump;
}
// 往右位置
if (current + 1 < arr.length && !visited[current + 1]) {
visited[current + 1] = true;
queue[right++] = current + 1;
}
// 往左位置
if (current > 0 && !visited[current - 1]) {
visited[current - 1] = true;
queue[right++] = current - 1;
}
// 往值相同元素的位置
for (let i = 0; i < map.get(arr[i]).length; i++) {
let tempIndex = map.get(arr[i])[i];
if (!visited[tempIndex]) {
visited[tempIndex] = true;
queue[right++] = tempIndex;
}
}
map.delete(arr[i]);
}
jump++;
}
return -1;
}