【leetcode】752.打开转盘锁

leetcode-752.png

是一个比较典型的BFS题目

将题目意思拆解就可以得到
1.得到所有组合
2.所有组合然后进行剪枝
3.遇到目标 target 直接 return

首先第一步,得到所有组合,直接用BFS来进行操作
使用queue来存放每一层的节点,然后来一层一层的进行入队出队操作,得到所有组合

BFS

var openLock = function (deadends, target) {
    let visited = new Set(deadends)
    if(visited.has('0000')){
        // 因为初始条件就是 lock = '0000'
        // 如果此时在 deadens里面就遇到,那就直接 return -1
        return -1
    }
    visited.add('0000')
    // ['xxxx', 得到'xxxx'所需要的步数]
    let queue = [['0000', 0]]
    while (queue.length) {
        let [node, step] = queue.shift()
        // 如果此时拿到的 node 就是target 直接 return
        if (node === target) {
            return step
        }
        // 获取 node只用一步就可以获取的所有 lock 组合
        let nexts = getNextLock(node)
        for (let next of nexts) {
            // 剪枝,visited 里面是访问过,以及不符合条件的 deadends 组合
            // 不符合条件则 到 nexts 里面再拿出一个来进行判断
            if (!visited.has(next)) {
                // 标记访问过的节点
                visited.add(next)
                // 添加到 queue 里面,并且表明 步数
                queue.push([next, step + 1])
            }
        }
    }
    return -1
};
// 获取 current 的下一步的所有组合
var getNextLock = function (current) {
    let allLock = []
    for (let i = 0; i < 4; ++i) {
        // 注意处理 字符类型 以及 数值类型,以防错误
        // Number(current[i]) + 1) !!!
        let up = current.substring(0, i) + (current[i] === '9' ? 0 : Number(current[i]) + 1) + current.substring(i + 1)
        let down = current.substring(0, i) + (current[i] === '0' ? 9 : Number(current[i]) - 1) + current.substring(i + 1)
        allLock.push(up)
        allLock.push(down)
    }
    return allLock
}

DFS

var openLock = function (deadends, target) {
    let visited = new Set(deadends)
    if (visited.has('0000')) {
        // 因为初始条件就是 lock = '0000'
        // 如果此时在 deadens里面就遇到,那就直接 return -1
        return -1
    }
    visited.add('0000')
    var dfs = function (current, step) {
        if (current === target) {
            return step
        }
        let minSteps = Infinity
        for (let next of getNextLock(current)) {
            if (!visited.has(next)) {
                visited.add(next)
                minSteps = Math.min(minSteps, dfs(next, step + 1))
                visited.delete(next)
            }
        }
    }
    let res = dfs('0000', 0)
    return res === Infinity ? -1 : res
};
// 获取 current 的下一步的所有组合
var getNextLock = function (current) {
    let allLock = []
    for (let i = 0; i < 4; ++i) {
        // 注意处理 字符类型 以及 数值类型,以防错误
        // Number(current[i]) + 1) !!!
        let up = current.substring(0, i) + (current[i] === '9' ? 0 : Number(current[i]) + 1) + current.substring(i + 1)
        let down = current.substring(0, i) + (current[i] === '0' ? 9 : Number(current[i]) - 1) + current.substring(i + 1)
        allLock.push(up)
        allLock.push(down)
    }
    return allLock
}

这里是使用DFS的思路来解决这个问题,但是会报错,栈溢出

这里DFS以及BFS的时间复杂度以及空间复杂度都是 O(10^4),4是锁的位数
因为DFS会压栈,如果不是最开始就检索到了,很容易会导致栈溢出
但是BFS不会,BFS一直在入队出队

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容