【LeetCode752】打开转盘锁(BFS)

简介: 【LeetCode752】打开转盘锁(BFS)每个节点有8个孩子节点,如题目给的第二个测试用例,start=0000时,4个位置分别可以向上转or向下转,得到1000、9000、0100、0900等8种情况。即这是一棵八叉树。即求解从start数字到target的最短路径。为了找到最小旋转次次数,利用BFS逐层查找,遇到target则返回树高度(层数)。

一、题目

中等题。

image.pngimage.png



二、思路

每个节点有8个孩子节点,如题目给的第二个测试用例,start=0000时,4个位置分别可以向上转or向下转,得到1000、9000、0100、0900等8种情况。即这是一棵八叉树。即求解从start数字到target的最短路径。为了找到最小旋转次次数,利用BFS逐层查找,遇到target则返回树高度(层数)。


需要关注两个点:

(1)防止走回头路,如从0000到1000,之后不能回到0000,不然就死循环了。所以需要借助哈希表。

(2)需要跳过died number,这也是关键。


有几个问题:

(1)为什么使用bfs。

初始化就是从0000开始,向周围8个结点发散,从无向图中来看就是从核心向周围不断扩散,同时记录扩散的圈数作为旋转次数,如果遇到deadends直接跳过,或者达到target直接返回即可。这种操作方式十分符合优化的BFS。


(2)为了方便,甚至可以不用哈希表,而是直接使用set集合(装dead num和已经遍历过的数字),即如果set有当前情况的数字或者dead num则跳过。


(3)需要将char类型转为数字后,再转为char类型,利用ASCII码做减法,用C++的c_str()和to_string也可以(但是用法不太好记)。


BFS使用队列,伪代码如下:

void BFS(int s){
  queue<int>q;
  q.push(s);
  while(!q.empty()){
    取出队首元素top;
    访问队首元素top;
    将队首元素出队pop;
    将top的下一层结点中未曾入队的结点全部入队,并设置为已入队;
  }
}

三、代码

class Solution {
public:
    int openLock(vector<string>& deadends, string target) {
        queue<string> q;
        //visited存储不阔能入队的节点,包括deadends和已访问过的节点
        unordered_set<string> visited;  
        visited.insert(deadends.begin(), deadends.end());
        if(visited.count("0000")){
            return -1;
        }
        //初始化哈希表
        int ans = 0;
        q.push("0000");
        while(!q.empty()){
            int length = q.size();
            for(int i = 0; i < length; i++){
                string curr = q.front();
                q.pop();
                //找到目标元素,直接返回ans
                if(curr == target){
                    return ans;
                }
                //处理curr周围的8个孩子节点
                for(int j = 0; j < 4; j++){
                    //自增1和自减1
                    for(int k = -1; k < 2; k += 2){
                        char a = (curr[j] -'0' + k + 10) % 10 + '0';
                        string newStr = curr;
                        newStr[j] = a;
                        //若哈希集合中找不到此状态,则加入哈希表,并入队
                        if(!visited.count(newStr)){
                            //入队,bfs
                            q.push(newStr);
                            visited.insert(newStr);//加入哈希集合
                        }
                    }
                }
            }
            //本层队列中元素处理完成,到达下一层
            ans++;
        }
        return -1;
    }
};
相关文章
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
【经典LeetCode算法题目专栏分类】【第4期】BFS广度优先算法:单词接龙、最小基因变化、二进制矩阵中的最短路径
|
5月前
|
存储 算法 数据可视化
广度优先搜索(BFS)+回溯解决LeetCode 126题:单词接龙 II
广度优先搜索(BFS)+回溯解决LeetCode 126题:单词接龙 II
|
5月前
|
存储 算法 数据可视化
LeetCode 题目 97:动态规划、递归到广度优先搜索BFS 实现交错字符串
LeetCode 题目 97:动态规划、递归到广度优先搜索BFS 实现交错字符串
|
5月前
|
搜索推荐 Java
单源最短路(只有一个起点)bfs,多源BFS,目录力扣675.为高尔夫比赛砍树,多源最短路问题:力扣542.01矩阵力扣1020.飞地的数量
单源最短路(只有一个起点)bfs,多源BFS,目录力扣675.为高尔夫比赛砍树,多源最短路问题:力扣542.01矩阵力扣1020.飞地的数量
|
6月前
【Leetcode 2583】二叉树中的第K大层和 —— 优先队列 + BFS
解题思路: - 使用队列保存节点,按层序依次保存该层节点 - 使用优先队列保存每层节点值的总和,最后剔除前k个大数即可得到
|
6月前
|
算法
leetcode-675:为高尔夫比赛砍树 (最短路径算法bfs,dijkstra,A*)
leetcode-675:为高尔夫比赛砍树 (最短路径算法bfs,dijkstra,A*)
56 0
|
算法 安全 Android开发
LeetCode 周赛上分之旅 # 37 多源 BFS 与连通性问题
学习数据结构与算法的关键在于掌握问题背后的算法思维框架,你的思考越抽象,它能覆盖的问题域就越广,理解难度也更复杂。在这个专栏里,小彭与你分享每场 LeetCode 周赛的解题报告,一起体会上分之旅。
46 0
|
算法
从小白开始刷算法 bfs篇 leetcode.107
从小白开始刷算法 bfs篇 leetcode.107
|
边缘计算 缓存 算法
LeetCode 双周赛 102,模拟 / BFS / Dijkstra / Floyd
昨晚是 LeetCode 双周赛第 102 场,你参加了吗?这场比赛比较简单,拼的是板子手速,继上周掉大分后算是回了一口血 😁。
111 0
从三道leetcode掌握广度优先搜索(BFS)
前言 BFS和DFS是如影随形的两种搜索方式,我们在上篇文章从三道leetcode掌握深度优先搜索(DFS)学习了递归的概念及DFS。不熟悉递归及DFS的同学可以先看看上篇文章,再阅读本篇比较好。