🌈【LeetCode.滑动谜题】- JavaScript =>双向BFS

233 阅读3分钟

「这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


题意描述

在一个 2 x 3 的板上(board)有 5 块砖瓦,用数字 1~5 来表示, 以及一块空缺用 0 来表示.

一次移动定义为选择 0 与一个相邻的数字(上下左右)进行交换.

最终当板 board 的结果是 [[1,2,3],[4,5,0]] 谜板被解开。

给出一个谜板的初始状态,返回最少可以通过多少次移动解开谜板,如果不能解开谜板,则返回 -1 。

示例:

输入:board = [[1,2,3],[4,0,5]] 输出:1 解释:交换 0 和 5 ,1 步完成

输入:board = [[1,2,3],[5,4,0]] 输出:-1 解释:没有办法完成谜板

输入:board = [[4,1,2],[5,0,3]] 输出:5 解释: 最少完成谜板的最少移动次数是 5 , 一种移动路径: 尚未移动: [[4,1,2],[5,0,3]] 移动 1 次: [[4,1,2],[0,5,3]] 移动 2 次: [[0,1,2],[4,5,3]] 移动 3 次: [[1,0,2],[4,5,3]] 移动 4 次: [[1,2,0],[4,5,3]] 移动 5 次: [[1,2,3],[4,5,0]]

分析

首先这类求路径的,一般都是搜索,肯定要想到深度优先搜索和广度优先搜索即dfs和bfs。这一题呢,会复杂一点。可以通过逆序数判断有没有解:0的移动不改变其逆序数的奇偶性,比如“12345”(去掉0)的逆序数为10(有解),“12354”的逆序数为9(无解); 所以当逆序数为奇数时,可以直接输出无解,大大减少了用bfs搜索的可能性。 当逆序数为偶数时,通过双向bfs,这样就可以求出最短路径了。

var slidingPuzzle = function(board) {
    let q1 = []
    let q2 = []
    let m1 = new Map()
    let m2 = new Map()
     let e = '123450'
    let s =''
    for(let i of board){
        for(let j of i){
            s+=j+''
        }
    } 
    if(e===s){
        return 0
    }
    m1.set(s,0)
    m2.set(e,0)
    q1.push(s)
    q2.push(e)
    let t 
    while(q1.length&&q2.length){
        if(q1.length<=q2.length){
            t = update(q1,m1,m2)
        }else{
            t = update(q2,m2,m1)
        }
        if(t!==-1){
            return t
        }

    }
    return -1
    function update(q,m,other){
        let str = q.shift()
        let pos = str.indexOf('0')
        let arr = next[pos]
        let temp 
        for(let i of arr){
          if(i<pos){
            temp = str.substring(0,i)+'0'+str.substring(i+1,pos)+str[i]+str.substring(pos+1)
          }else{
            temp = str.substring(0,pos) + str[i] +str.substring(pos+1,i)+'0'+str.substring(i+1)
          }
          if(m.has(temp)){
              continue
          }
          if(other.has(temp)){
              return other.get(temp) + 1 + m.get(str)
          }else{
              m.set(temp,m.get(str)+1)
              q.push(temp)
          }
        }
        return -1
    }
};
最后

其实除了双向bfs,还也可以利用到优先队列去实现配合哈希表去实现,具体的代码还没有写过,大家有兴趣可以试试。


感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤