(字节跳动笔试题)前端代码题第3题 迷宫最短路径问题
今天做头条的笔试题,3道手撕代码题,前两道基本写出来了,但不知什么原因没能ac,最后一题没时间做了,下来花了1个小时,基本算写了一个可行的解法,回溯法,代码比较初级混乱,大神请忽略~~
问题描述:
输入一个迷宫地图如下所示,其中-2代表起始位置,-3代表终点位置,0代表普通路径,其他值为‘传送门’,每次行进一格,如果遇到传送门,可选择传送(直接走到数值相同的点)或者不传送,求从初始位置到终点的最短路径(题目好像说明每种传送门有且仅有一对)
1 0 -1 1 -2 0 -1 -3 2 2 0 0
思路:
我的代码直接记录了所有可行路径的节点顺序,题意是要求最短路径,这个比较好改
1.首先记录始终点坐标,起点作为递归的开始,用一个变量curSteps记录当前路径
2.每次进入一个位置,先判断是否为终点,如果是,就推入curSteps记录可行路径
3.如果不是终点,判断是否可传送,选择传送,并标记传送门关闭(用'x'标记关闭的位置)
4.向上走。判断边界条件(数组下标不越界),以及是否是关闭位置,选择向上走并关闭位置
5.向下走。同4
6.向左走。同4
7.向右走。同4
8.清除关闭状态,递归第2~8步
代码
let map = [
[1, 0, -1, 1],
[-2, 0, -1, -3],
[2, 2, 0, 0]
]
// 记录一下地图,用于清除关闭状态
let mapCopy = map.slice(0)
// 查找坐标
function findPos (map, val) {
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map[0].length; j++) {
if (map[i][j] == val) return [i, j]
}
}
}
// 查找起终点
let start = findPos(map, -2)
let end = findPos(map, -3)
// 某坐标是否是终点
function isEnd (map, x, y) {
return map[x][y] == -3 ? true : false
}
// 寻找传送门终点
function findDoor (map, x, y) {
// 起点,终点和0都没传送门
if (map[x][y] == -2 || map[x][y] == -3 || map[x][y] == 0 || map[x][y] == 'x') return false
let val = map[x][y]
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map[0].length; j++) {
if (map[i][j] == map[x][y] && (i != x || j != y))
return [i, j]
}
}
return false
}
// 设置传送门关闭
function setDoorClose (map, x, y) {
for (let i = 0; i < map.length; i++) {
for (let j = 0; j < map[0].length; j++) {
if (map[i][j] == map[x][y])
map[i][j] = 'x'
}
}
}
// 寻找所有可行路径,并返回路径总步数
function findPaths (map, x, y, curSteps, allSteps) {
// 如果是终点,则推入步数
if (isEnd(map, x, y)) {
curSteps += '(' + x + ',' + y + ')'
allSteps.push(curSteps)
curSteps = []
return
}
// 如果不是终点,记录当前坐标
curSteps += '(' + x + ',' + y + ')=>'
// 传送
if (findDoor(map, x, y)) {
let door = findDoor(map, x, y)
// 如果传送过了,则不可以再走进传送门
setDoorClose(map, door[0], door[1])
findPaths(map, door[0], door[1], curSteps, allSteps)
}
// 非封锁的点才可以走
// 向上走 走过的点不允许再走
if (x - 1 >= 0 && map[x-1][y] != 'x') {
map[x][y] = 'x'
findPaths(map, x - 1, y, curSteps, allSteps)
}
// 向下走
if (x + 1 < map.length && map[x+1][y] != 'x') {
map[x][y] = 'x'
findPaths(map, x + 1, y, curSteps, allSteps)
}
// 向左走
if (y - 1 >= 0 && map[x][y-1] != 'x') {
map[x][y] = 'x'
findPaths(map, x, y - 1, curSteps, allSteps)
}
// 向右走
if (y + 1 < map[0].length && map[x][y+1] != 'x') {
map[x][y] = 'x'
findPaths(map, x, y + 1, curSteps, allSteps)
}
// 解除传送门封锁
map = mapCopy
}
let allSteps = []
let curSteps = []
findPaths (map, start[0], start[1], curSteps, allSteps)
console.log(allSteps)代码输出:
Array(3) ["(1,0)=>(0,0)=>(0,3)=>(1,3)", "(1,0)=>(0,0)=>(0,3)=>(0,2)=>(1,2)=>(2,2)=>(2,3)=>(1,3)", "(1,0)=>(0,0)=>(0,3)=>(0,2)=>(1,2)=>(1,3)"]
一共找到3条路径,其中最短的步数为3
#字节跳动笔试##字节跳动##前端工程师##笔试题目#
查看4道真题和解析