先看题目:

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

在做队列的专项的时候遇到,思考了20分钟左右无任何方案,搜了B站花花酱的视频讲解才搞懂(https://www.bilibili.com/video/av31636797?t=385)。

这道题算是典型的无向图问题,每个数字表示图中一个节点,"0000"表示根节点,每个节点由四位数组成,其中每个数每次转动存在两种变形,所以一次转动,节点有八个子节点,如下图:

将待遍历的节点添加到队列中,遍历完成,则将节点添加到死节点数组中。从图中可看出,第一次遍历有八种可能,如果某个节点和目标节点相等,则返回当前深度即可,不等的话,如果没有访问过它或者死节点数组中没有它,即我们需要去遍历它的子节点,这时候将它加入到队列里,以待访问它的子节点。同时将它加入到死节点数组中,防止后续重复访问该节点。因为遍历每一层的时候,都会更新队列,所以一开始就要知道每层遍历的数量。c语言不像其它高级语言,有现成的队列结构拿来使用,需要自己实现,此外,死节点数组使用了哈希数组,因为每个节点都是10000以内的一个数字,如果使用strcmp的话耗时可能更久。

下面是c代码的解法,只看最下面的核心函数即可,前面代码时关于队列和哈希表的,可略过:

/* BFS求解 */#define MAX 10001//循环队列
struct queue {int head, end, length;char a[10001][5];
};//入队
int enQueue(struct queue *q, char *n)
{if (q->length >= MAX - 1)return -1;else{strcpy(q->a[q->end], n);q->end = (q->end + 1) % MAX;q->length++;return 0;}
}//出队
int deQueue(struct queue *q, char *n)
{if (q->length == 0)return -1;else{strcpy(n, q->a[q->head]);q->length--;q->head = (q->head + 1) % MAX;}return 0;
}//获取队列长度
int queueLength(struct queue *q)
{return q->length;
}//判断队列是否为空
int isQueueEmpty(struct queue *q)
{if (q->length == 0)return 1;elsereturn 0;
}//判断t是否在head中
int inDead(int *dead, char *t)
{int i, v;for (i = 0, v = 0; i < 4; i++)v = v * 10 + (t[i] - '0');if (dead[v] == 1)return 1;elsereturn 0;}//添加到哈希队列中
void enDead(int *dead, char *t)
{int i, v;for (i = 0, v = 0; i < 4; i++)v = v * 10 + (t[i] - '0');dead[v] = 1;return ;
}int openLock(char ** deadends, int deadendsSize, char * target){int i,j,k, ret, len, steps = 0;char start[] = "0000", n[5] = {0}, curr[5] = {0};struct queue *q;q = (struct queue *)malloc(sizeof(struct queue));if (!q) exit(1);q->length = q->head = q->end = 0;int dead[10000] = {0};for (i = 0; i < deadendsSize; i++)enDead(dead, deadends[i]);if (inDead(dead, start))return -1;enQueue(q, start);while(!isQueueEmpty(q)){++steps;len = queueLength(q);for (k = 0; k < len; k++){deQueue(q, curr);            for (i = 0; i < 4; i++){for (j = -1; j < 2; j+=2){strcpy(n, curr);n[i] = (n[i] - '0' + j + 10)%10 + '0';if (!strcmp(n, target)) return steps;if (inDead(dead, n)) continue;enQueue(q, n);enDead(dead,n);}}}}return -1;
}

参考资料:

1. https://www.bilibili.com/video/av31636797?t=385

=============================================================================================

Linux应用程序、内核、驱动开发交流讨论群(745510310),感兴趣的同学可以加群讨论、交流、资料查找等,前进的道路上,你不是一个人奥^_^。

leetcode 752. 打开转盘锁 c代码相关推荐

  1. leetcode —— 752. 打开转盘锁

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

  2. LeetCode 752. 打开转盘锁 (C#实现)——队列,广度优先搜索

    一.代码实现 思路:使用先进先出的队列,广度优先搜索,使用字典可大幅减少遍历时间 问题:https://leetcode-cn.com/problems/open-the-lock/submissio ...

  3. LeetCode 752. 打开转盘锁(图的BFS最短路径)

    1. 题目 你有一个带有四个圆形拨轮的转盘锁.每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' .每个拨轮可以自由旋转:例如把 ...

  4. 血战力扣752.打开转盘锁

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

  5. leetcode 752. Open the Lock | 752. 打开转盘锁(BFS)

    题目 https://leetcode.com/problems/open-the-lock/ 题解 先写了个 DFS,超时了. 看了下 Related Topics,提示说应该是 BFS.这已经不是 ...

  6. 打开转盘锁 ,易懂的BFS解法

    打开转盘锁 LeetCode752 题目描述: 你有一个带有四个圆形拨轮的转盘锁.每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', ' ...

  7. 【广度优先搜索】N叉树的层序遍历 | 腐烂的橘子 | 单词接龙 | 最小基因变化 | 打开转盘锁

  8. java之Synchronized(锁住对象和锁住代码)

    1.问题 Synchronized我们一般都知道是锁,但是我们怎么区分是锁对象还是锁代码呢? 2.测试Demo package leetcode.chenyu.test;public class Sy ...

  9. Android 程序保活,锁机代码

    前言 保活:如何让我们的app在Android系统不被杀死 保证存活,简单做法就是提升程序的优先级,看完本文一些流氓锁机你也会了哦.但锁机源码我不打算提供 为了防止某些恶心的人直接复制然后在市面上搞破 ...

最新文章

  1. mouseOver/mouseOut 与 rollOver/rollOut的区别
  2. opencv 灰度图
  3. python模块基础之getpass模块
  4. _ZNote_Chrom_插件_Chrom运行Android软件_APK
  5. 学好SQL--MySQL简单使用(3)
  6. 关于DataFormWebPart中CreatedModifiedInfo信息的分开使用
  7. P2660 zzc 种田( python3实现)
  8. 搭建一个jumpserver跳板机
  9. 【课程】MIT最新深度学习课程集
  10. javascript 模仿点击链接
  11. wav文件头修复_windows文件夹分析(xp版,网络整理)
  12. pandas后几行_天秀!Pandas还能用来写爬虫?
  13. java代码审计文章集合
  14. 机器学习 | 算法笔记- 决策树(Decision Tree)
  15. android镜子app,Android镜子应用 一面可编程的镜子
  16. 硬件设计-USB2.0电路设计
  17. 批量将不同文件夹目录中的文件统一提取到同一个文件夹中
  18. Mikrotik RouterOS路由器和华为交换机链路聚合+VRRP+单线多拨
  19. Error starting ApplicationContext.
  20. 图文电视related

热门文章

  1. 【面试题41】和为s的两个数字VS和为s的连续整数序列
  2. 消除文法中一切左递归算法
  3. uva 12100 Printer Queue 优先级队列模拟题 数组模拟队列
  4. 如何杀死进程及子进程
  5. php获取函数里参数吗,php函数中获取参数信息方法(记录)
  6. 比较双曲正切tanh与sigmoid激活函数的性能差异
  7. linux查看usb设备文件,linux – 确定USB设备文件路径
  8. 【UWB】数学建模 E 题目个人解题答案 - 2021年第十八届华为杯
  9. 【STM32】跑马灯实验主要程序代码分析
  10. 【Android工具】更新手机视频流媒体客户端播放器OPlayer