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

#字节跳动笔试##字节跳动##前端工程师##笔试题目#
全部评论
前两道是什么题啊
点赞 回复
分享
发布于 2020-03-16 06:34
跟你思路差不多,但是没有ac,好像过了两三个样例
点赞 回复
分享
发布于 2020-03-16 09:59
联想
校招火热招聘中
官网直投
为啥我是四道题
点赞 回复
分享
发布于 2020-03-16 10:47
这是道题就是采用宽度优先遍历解决,除了上下左右之外,还有传送门的目的地需要考虑,思路弄对了不用那么麻烦。
点赞 回复
分享
发布于 2020-03-16 15:17
&只有代码题吗?
点赞 回复
分享
发布于 2020-04-09 16:04
能分享一下前面两个的代码吗
点赞 回复
分享
发布于 2020-04-09 20:52

相关推荐

6 14 评论
分享
牛客网
牛客企业服务