zoukankan      html  css  js  c++  java
  • LeetCode752 打开转盘锁

    你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有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
    

     

    提示:

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

    //章节 - 队列和栈    
    //二、队列与广度优先搜索
    //2.打开转盘锁
    /*
    算法思想:
        这也是一道很有意思的题,其实本质就是个迷宫遍历的问题,只不过相邻位置不再是上下左右四个位置,而是四位数字每个都加一减一,总共有八个相邻的位置。与经典BFS遍历迷宫解法唯一不同的就是找下一个位置的地方,这里我们要遍历四位数字的每一位,然后分别加1减1,我们用j从-1遍历到1,遇到0跳过,也就是实现了加1减1的过程。然后我们要计算要更新位上的数字,为了处理9加1变0,和0减1变9的情况,我们统一给该位数字加上个10,然后再加或减1,最后再对10取余即可,注意字符和整型数之间通过加或减'0'来转换。我们用结果res来记录BFS遍历的层数,如果此时新生成的字符串等于target了,直接返回结果res,否则我们看如果该字符串不在死锁集合里,且之前没有遍历过,那么加入队列queue中,之后将该字符串加入visited集合中即可。注意这里在while循环中,由于要一层一层的往外扩展,一般的做法是会用一个变量len来记录当前的q.size(),博主为了简洁,使用了一个trick,就是从q.size()往0遍历,千万不能反回来,因为在计算的过程中q的大小会变化,如果让k < q.size() 为终止条件,绝b会出错,而我们初始化为q.size()就没事。
    */
    //算法实现:
    class Solution {
    public:
        int openLock(vector<string>& deadends, string target) {
            unordered_set<string> deadlock(deadends.begin(), deadends.end());
            if (deadlock.count("0000")) 
                return -1;
            int res = 0;
            unordered_set<string> visited{{"0000"}};
            queue<string> q{{"0000"}};
            while (!q.empty()) {
                ++res;
                for (int k = q.size(); k > 0; --k) {
                    auto t = q.front(); q.pop();
                    for (int i = 0; i < t.size(); ++i) {
                        for (int j = -1; j <= 1; ++j) {
                            if (j == 0) 
                                continue;
                            string str = t;
                            str[i] = ((t[i] - '0') + 10 + j) % 10 + '0';
                            if (str == target) 
                                return res;
                            if (!visited.count(str) && !deadlock.count(str)) 
                                q.push(str);        
                            visited.insert(str);
                        }
                    }
                }
            }
            return -1;
        }
    };
  • 相关阅读:
    互联网之用
    数据结构C语言>数组>一维数组表示二维数组
    关于启动Activity之间的及普通按钮的点击事件
    创建一个新的安卓应用程序 设置主Activity
    关于Activity之间传送数据
    Displaying a Tree control as a pop up for a Flex PopUpButton control (转载)
    Creating an undraggable Alert control in Flex (转载)
    Embedding external files using [Embed] (转载:学习如何嵌入外部文件)
    Creating unique identifiers for objects using the getUID() (转载)
    Adding animations and effects to Flex tool tips (转载)
  • 原文地址:https://www.cnblogs.com/parzulpan/p/10061567.html
Copyright © 2011-2022 走看看