130 lines
4.0 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* @param {number[][]} board
* @return {number}
*/
const snakesAndLadders = function (board) {
};
/*
/*
把棋盘的每一个位置看成图的一个顶点,每一个顶点都有六个有向边指向后面的六个位置,也就是后面的六个顶点,有的顶点比较特殊,
它不指向后面的六个顶点,而是指向其他的顶点,我们要求的就是到达最后一个位置的顶点所需的最少步数,到这里我们很容易发现,这
是一个图的BFS题目我们从最初的位置一层一层的往外扩需要用几层就是几步
*/
function f1(board) {
// 定义一个长度为n*n+1的一维数组将board压缩减少计数难度
const n = board.length;
const size = n * n;
const arr = new Array(size + 1); // 0位置不需要这样就能和board一一对应
let idx = 1; // 棋盘初始位置
let leftToRight = true; // s行遍历board
for (let i = n - 1; i >= 0; i--) {
if (leftToRight) {
for (let j = 0; j < n; j++) {
arr[idx++] = board[i][j];
}
} else {
for (let j = n - 1; j >= 0; j--) {
arr[idx++] = board[i][j];
}
}
leftToRight = !leftToRight;
}
// bfs队列从第一个位置开始[1,0]表示,到达第一个位置最少只需要一步
const queue = [[1, 0]];
const visited = new Array(size + 1).fill(false); // 防止每一层的元素重复加入到下一层
visited[1] = true;
while (queue.length) {
const [cur, step] = queue.shift();
// 查看邻接的六个顶点
for (let i = 1; i <= 6; i++) {
let next = cur + i; // 下一个顶点位置
// 越界,忽略这个顶点
if (next > size) {
continue;
}
// 如果遇到蛇和梯子立即调整指定位置
if (arr[next] !== -1) {
next = arr[next];
}
// 如果邻接顶点就是目标位置直接放回到达当前顶点的步数在加1
if (next === size) {
return step + 1;
}
// 如果元素没有被访问将其加入队列,扩展下一层
if (!visited[next]) {
visited[next] = true;
queue.push([next, step + 1]);
}
}
}
return -1; // 不可达
}
/*
将二维数组变成一维数组需要log(n*n)的时间复杂度n为棋牌大小相等于一开始就遍历了整个棋盘一遍如果能实时计算当前位置到其他位置
在board中的位置可以大大减少时间复杂度。
思考假设我们有一个大小为n的棋牌计数位置place(1 ~ n*n)在board中的坐标首先计算行行非常好计算r = (place - 1) / n,那么列
还是 (place-1) % n吗在这个题目不是的因为棋牌是按照s行走的偶数行从左往右奇数行从右往左偶数行显然是(place-1)%n那么技术行只需要将n
减去它即可
*/
const id2rc = (id, n) => {
const r = Math.floor((id - 1) / n);
let c = (id - 1) % n;
if (r % 2 === 1) {
c = n - 1 - c;
}
return [n - 1 - r, c];
};
function f2(board) {
const n = board.length;
const size = n * n;
// BFS
const queue = [[1, 0]];
const visited = new Array(size + 1).fill(false); // 防止每一层的元素重复加入到下一层
visited[1] = true;
while (queue.length) {
const [cur, step] = queue.shift();
// 查看邻接的六个顶点
for (let i = 1; i <= 6; i++) {
let next = cur + i; // 下一个顶点位置
// 越界,忽略这个顶点
if (next > size) {
continue;
}
const [r, c] = id2rc(next, n);
// 如果遇到蛇和梯子立即调整指定位置
if (board[r][c] !== -1) {
next = board[r][c];
}
// 如果邻接顶点就是目标位置直接放回到达当前顶点的步数在加1
if (next === size) {
return step + 1;
}
// 如果元素没有被访问将其加入队列,扩展下一层
if (!visited[next]) {
visited[next] = true;
queue.push([next, step + 1]);
}
}
}
return -1; // 不可达
}