leet_code_752.打开转盘锁(广度)

简介: leet_code_752.打开转盘锁(广度)

题目信息


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


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


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


字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。


示例 1:

输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202"
输出:6
解释:
可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。
注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的,
因为当拨动到 "0102" 时这个锁就会被锁定。

示例 2:

输入: deadends = ["8888"], target = "0009"
输出:1
解释:
把最后一位反向旋转一次即可 "0000" -> "0009"。

示例 3:

输入: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
输出:-1
解释:
无法旋转到目标数字且不被锁定。

示例 4:

输入: deadends = ["0000"], target = "8888"
输出:-1


提示:

死亡列表 deadends 的长度范围为 [1, 500]。

目标数字 target 不会在 deadends 之中。

每个 deadends 和 target 中的字符串的数字会在 10,000 个可能的情况 ‘0000’ 到 ‘9999’ 中产生。


代码实现

package com.honsupply.api.core.util.logger;
import java.util.*;
public class Test {
    public static void main(String[] args) {
        String[] deadends = {"0201", "0101", "0102", "1212", "2002"};
        String target = "0202";
        System.out.println(openLock(deadends, target));
    }
    /** 解决转盘锁的问题
     * 本题为自己的思路,效率不是很高,如需更有答案,请移步力扣,搜索"打开转盘锁"。
     * 解决问题的思想:每次可以转动一个,转动一次步长为1,第一次转动可以为"1000","1010","9000","0900"...
     * 将一次可转动的放到队列中,然后插入一个null值,然后基于前一次的基础上转动第二下
     * 遇到第一个插入的null时代表第一轮循环完毕,则步数+1,然后插入一个新的null值,代表在此之前的均为前一次步数可达的范围。
     */
    private static int openLock(String[] deadends, String target){
        if(target.equals("0000")) return 0;
        Set<String> set = new HashSet<>();
        Collections.addAll(set, deadends);
        // 定义出现过的方案,以防重复,进入死循环
        Set<String> answerSet = new HashSet<>();
        answerSet.add("0000");
        Queue<String> queue = new LinkedList<>();
        queue.offer("0000");
        // 插入null值,用于计算步长
        queue.offer(null);
        int step = 0;
        // 如果队列不为空,则一直循环下去,如果为空,且未找到答案,则返回-1
        while(!queue.isEmpty()){
            // 取队列的第一个值
            String answer = queue.remove();
            // 遇见null,则步长+1
            if(answer == null){
                step ++;
                // 如果null后面还有数据,则插入一个新的null,标志一轮结束
                if(queue.peek() != null){
                    queue.offer(null);
                }
            // 匹配到正确的答案,返回步长
            }else if(answer.equals(target)){
                return step;
            // 当遇到deadends内的值时,则无需继续向下找,故跳出for循环
            }else if(!set.contains(answer)){
                // 每次可以转动第1.2.3.4的数值
                for (int i = 0; i < 4; i ++){
                    // 取当前位置的数字+1 or -1。
                    // 如果为9,+ 1 则变成0
                    // 如果为0,- 1 则变成9
                    int number = Integer.parseInt(answer.substring(i, i+1));
                    int nextNum = number == 9 ? 0 : number+1;
                    String next = answer.substring(0, i) + String.valueOf(nextNum) + answer.substring(i + 1, 4);
                    if(!answerSet.contains(next)){
                        queue.offer(next);
                        answerSet.add(next);
                    }
                    int prevNum = number == 0 ? 9 : number-1;
                    String prev = answer.substring(0, i) + String.valueOf(prevNum) + answer.substring(i + 1, 4);
                    if(!answerSet.contains(prev)){
                        queue.offer(prev);
                        answerSet.add(prev);
                    }
                }
            }
        }
        return -1;
    }
}


目录
相关文章
|
算法 Cloud Native
【刷题日记】513. 找树左下角的值
本次刷题日记的第 74 篇,力扣题为:513. 找树左下角的值 ,中等
Leecode 面试题62. 圆圈中最后剩下的数字
Leecode 面试题62. 圆圈中最后剩下的数字
70 0
|
前端开发
前端知识学习案例12vs code-向上或者向下插入行
前端知识学习案例12vs code-向上或者向下插入行
49 0
前端知识学习案例12vs code-向上或者向下插入行
|
算法
leet_code_202.快乐数(快慢指针)
leet_code_202.快乐数(快慢指针)
62 0
|
前端开发
前端知识学习案例8vs code-剪切操作
前端知识学习案例8vs code-剪切操作
47 0
前端知识学习案例8vs code-剪切操作
|
前端开发
前端知识学习案例10vs code-向上或者向下移动
前端知识学习案例10vs code-向上或者向下移动
72 0
前端知识学习案例10vs code-向上或者向下移动
|
算法 索引
【切图仔的算法修炼之旅】LeetCode141:判断链表是否有环
【切图仔的算法修炼之旅】LeetCode141:判断链表是否有环
110 0
【切图仔的算法修炼之旅】LeetCode141:判断链表是否有环
|
算法 索引
【切图仔的算法修炼之旅】LeetCode1991:找到数组中的中间位置
【切图仔的算法修炼之旅】LeetCode1991:找到数组中的中间位置
116 0
|
算法 Java
『牛客|每日一题』AB5 点击消除
基础算法无论在研究生面试还是求职面试都是十分重要的一环,这里推荐一款算法面试神器:牛客网-面试神器;算法题只有多刷勤刷才能保持思路与手感,大家赶紧行动起来吧(温馨提示:常见的面试问答题库也很nice哦 https://www.nowcoder.com/link/pc_csdncpt_ll_sf
80 0
『牛客|每日一题』AB5 点击消除
|
测试技术 C++
【LeetCode752】打开转盘锁(BFS)
【LeetCode752】打开转盘锁(BFS) 每个节点有8个孩子节点,如题目给的第二个测试用例,start=0000时,4个位置分别可以向上转or向下转,得到1000、9000、0100、0900等8种情况。即这是一棵八叉树。即求解从start数字到target的最短路径。为了找到最小旋转次次数,利用BFS逐层查找,遇到target则返回树高度(层数)。
137 0
【LeetCode752】打开转盘锁(BFS)