752. 打开转盘锁(BFS)


752. 打开转盘锁

题目

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。

锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。

列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。

字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。
在这里插入图片描述
在这里插入图片描述
提示:

  • 死亡列表 deadends 的长度范围为 [1, 500]。
  • 目标数字 target 不会在 deadends 之中。
  • 每个 deadends 和 target 中的字符串的数字会在 10,000 个可能的情况 - ‘0000’ 到 ‘9999’ 中产生。

解题思路

其实就是问从0000转到目标密码要的最少次数。BFS模板即可解决

代码

class Solution {
    public int openLock(String[] deadends, String target) {
        // 记录需要跳过的死亡密码
        Set<String> deads = new HashSet<>();
        for (String s : deadends) {
            deads.add(s);
        }
        //防走回头路
        Set<String> visited = new HashSet<>();
        //核心数据结构
        Queue<String> q = new LinkedList<>();

        //把起点'0000'加入到q
        q.offer("0000");
        visited.add("0000");
        int step = 0;//0000是初始状态,没转动就这样,所以步数无需从1开始

        while (!q.isEmpty()) {
            int sz = q.size();
            for (int i = 0; i < sz; i++) {
                String cur = q.poll();

                // 判断是否合法.是否到达终点
                if (deads.contains(cur)) {
                    continue;
                }
                if (cur.equals(target)) {
                    return step;
                }

                // 将cur相邻的节点加入队列
                for (int j = 0; j < 4; j++) {
                    String up = plusOne(cur, j);
                    if (!visited.contains(up)) {
                        q.offer(up);
                        visited.add(up);
                    }
                    String down = minusOne(cur, j);
                    if (!visited.contains(down)) {
                        q.offer(down);
                        visited.add(down);
                    }
                }

            }
            step++;
        }
        return -1;
    }


    /**
     * 把s[j]向上拨动一次
     */
    public String plusOne(String s, int j) {
        char[] ch = s.toCharArray();
        if (ch[j] == '9') {//9再向上拨动一下就是0了
            ch[j] = '0';
        } else {
            ch[j] = (char) (ch[j] + 1);//否则正常增大一位数即可
        }
        return new String(ch);
    }

    /**
     * 把s[j]向下拨动一次
     */
    public String minusOne(String s, int j) {
        char[] ch = s.toCharArray();
        if (ch[j] == '0') {//0再向下拨动一下就是9了
            ch[j] = '9';
        } else {
            ch[j] = (char) (ch[j] - 1);//否则正常减小一位数即可
        }
        return new String(ch);
    }
}

文章作者: fFee-ops
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 fFee-ops !
评论
  目录