(字节跳动笔试题)前端代码题第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
#字节跳动笔试##字节跳动##前端工程师##笔试题目#