一、 题目描述

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

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

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

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

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

二、 代码思路

leetcode官方题解

本题并不是动态规划题,而是使用的一种很好的BFS思想。以往BFS总是用在图、树,本题BFS有了更灵活的一种用法。

在图中,BFS的下一个元素可以是四个方向。在二叉树或者多叉树中,BFS的下一个元素是该节点的孩子节点。

本题可以与岛屿问题类比,岛屿问题枚举下一个元素是四个方向,本题枚举是status + 1的所有可能性,status码就是指当前密码锁的值(比如说”0123“),由于每次我们拨动密码锁只能拨动一位数,所以我们从当前status枚举nextStatus,就是status + 1 。并且,可以将其作为下一个元素放入BFS队列。

同样的,本题还借用了BFS求最短路径问题的思想,也可以理解为从"0000"出发,找到从"0000"到 target 正确密码的最短距离。

具体地,我们在一开始将 (0000,0) 加入队列,并使用该队列进行广度优先搜索。在搜索的过程中,设当前搜索到的数字为 status,旋转的次数为 step,我们可以枚举 status 通过一次旋转得到的数字。设其中的某个数字为 next_status,如果其没有被搜索过,我们就将 (nextStatus, step+1) 加入队列。如果搜索到了 target,我们就返回其对应的旋转次数。

为了避免搜索到死亡数字,我们可以使用哈希表存储 deadends 中的所有元素,这样在搜索的过程中,我们可以均摊 O(1) 地判断一个数字是否为死亡数字。同时,我们还需要一个哈希表存储所有搜索到的状态,避免重复搜索。

如果搜索完成后,我们仍没有搜索到 target,说明我们无法解锁,返回 −1。

边界值判断:一定要注意边界值的判断以及访问数组的判断,做任何题都要考虑。

三、代码题解


//动态规划 求最优解
//并不是,而是使用的一种很好的BFS思想。以往BFS总是用在图、树,本题BFS有了更灵活的一种用法。
//可以与岛屿问题类比,岛屿问题枚举下一个元素是四个方向,本题枚举是status码 + 1的可能性
func openLock(deadends []string, target string) int {//边界值判断if target == "0000" {return 0}//初始化操作,HashMap判断我BFS的数字是否属于死亡数字,可能需要访问数组。deads := make(map[string]bool)for _, str := range(deadends) {deads[str] = true}//如果target 或者 0000 本身就是deadends_,ok := deads[target]_,ok1 := deads["0000"]if ok || ok1{return -1;}//处理枚举下一个元素//这里会出问题,修改nextStatus居然同时也会把statusCharArray修改掉,就离谱,可能是修改的同一块区域getNextStatus := func(status string) (ret []string){statusCharArray := []byte(status)for i,data := range(statusCharArray) {nextStaus := statusCharArraytemp := data + 1if temp > '9' {nextStaus[i] = '0'} else {nextStaus[i] = temp}ret = append(ret, string(nextStaus))temp = data - 1if temp < '0' {nextStaus[i] = '9'} else {nextStaus[i] = temp}ret = append(ret, string(nextStaus))nextStaus[i] = data}return ret}//BFS操作//go 中是用切片实现队列的type node struct {status stringstep int}//队列辅助BFS//var queue []node//queue[0] = node{"0000",0}queue := []node{{"0000", 0}}//访问数组visited := make(map[string] bool)for len(queue) != 0 {statusNode := queue[0]queue = queue[1:]for _,nextStatus := range getNextStatus(statusNode.status) {_,ok = deads[nextStatus]//如果元素被访问,那么就会存在于visited数组中,ok1的返回值为ture 反之_,ok1 = visited[nextStatus]if !ok && !ok1{step := statusNode.stepstep++if nextStatus == target {return step}nextStatusNode := node{nextStatus, step}queue = append(queue, nextStatusNode)visited[nextStatus] = true}}}/*queue := list.New()queue.PushFront("0000")for queue.Len() != 0 {var status stringstatus := queue.Front()queue.Remove(status)for _,nextStatus := range getNextStatus(string(status)) {if nextStatus}}*/return -1
}

【leetcode】开密码锁相关推荐

  1. 剑指 Offer II 109. 开密码锁

    链接:剑指 Offer II 109. 开密码锁 题解: class Solution { public:int openLock(vector<string>& deadends ...

  2. offer_II_109开密码锁

    开密码锁 一个密码锁由 4 个环形拨轮组成,每个拨轮都有 10 个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' .每个拨轮可以自由旋转:例如 ...

  3. 青云算法面试题干货-开密码锁-LeetCode第752题

    问题:给你一个包含四个环形转轮的密码锁,每个转轮上10个格子对应从'0'到'9'的10个数字.这些转轮可以向两个方向自由转动,也就是可以从'0'转到'9',也可以从'9'转到'0'.每一步你只可以转一 ...

  4. 剑指offer109:开密码锁

    题目: 一个密码锁由 4 个环形拨轮组成,每个拨轮都有 10 个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' .每个拨轮可以自由旋转:例如把 ...

  5. Leetcode刷题笔记——剑指offer II (六)【图】

    文章目录 图 695. 岛屿的最大面积 剑指 Offer II 106. 二分图 (每条边的两个结点都来自不同的集合) 剑指 Offer II 107. 矩阵中的距离 (最短路问题,建图,BFS) 剑 ...

  6. LeetCode刷题 _「剑指 Offer]专项突破版

    第01天 整数 剑指 Offer II 001. 整数除法 class Solution:# 时间复杂度:O(logn), 空间复杂度:O(1)def divideCore(self, dividen ...

  7. LeetCode经典300题【C++版】

    102-二叉树的层序遍历 /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* ...

  8. 试设计递归算法dfs traverse_BFS 算法框架套路详解

    作者:labuladong 公众号:labuladong 后台有很多人问起 BFS 和 DFS 的框架,今天就来说说吧. 首先,你要说 labuladong 没写过 BFS 框架,这话没错,今天写个框 ...

  9. 2021秋招-算法-BFS-DFS

    LeetCode刷题总结-DFS.BFS和回溯法篇 一.深度优先搜索 一.字符匹配问题 [1.lc-301. 删除无效的括号-困难] 二.数组或字符串问题 [1. lc-329. 矩阵中的最长递增路径 ...

最新文章

  1. 腾讯有史以来最高职级研究员是谁?
  2. SQL on Linux Run on Docker
  3. 进程线程006 Windows线程切换-线程优先级
  4. 开发者新春回血大礼包助你2021畅行无压力!
  5. 人工智能、物联网和大数据如何拯救蜜蜂
  6. Eclipse新建web项目出现The superclass javax.servlet.http.HttpServlet was not found on the Java Build Path
  7. Web服务(Apache、Nginx、Tomcat、Jetty)与应用(LAMP、CMS-WordPressGhost、Jenkins、Gitlab)
  8. 51Nod1469 淋漓尽致子串
  9. 王炸吐血整理60个Redis面试题,全网最全了
  10. 拉面说:如何成为速食拉面独角兽
  11. 有mysql文件怎么运行不了_MySQL安装常见问题(找不到文件,系统服务无法启动...)...
  12. postgresql如何让主键自增
  13. 从零开始通过 Artifactory 搭建公网的 maven 仓库
  14. Vue 项目在 IE11 中数据更改后页面数据无变化
  15. 绿幕抠图-为你的想象插上翅膀
  16. uint8_t范围_uint8_t / uint16_t / uint32_t /uint64_t数据类型详解
  17. POI java.lang.IllegalArgumentException: Merged region xxx must contain 2 or more cells问题解决
  18. input 数字类型
  19. 基于qiankun.js的微前端应用实战
  20. Android 6.0 AppOps 简介

热门文章

  1. 085 《穷查理宝典》简记
  2. 数藏行业公众号裂变,单日拉新8w+,实现低成本获客?
  3. 3-2-1 程序控制结构-while循环结构-多次求解一元二次方程?-while循环常见错误?
  4. 【Mysql系列】MySQL创建数据库、CURD的操作
  5. android pie_Android Pie中的新安全功能,以及为什么对它们感到兴奋
  6. 命令行导入 .dmp文件,亲测可行
  7. 基于jsp servlet javabean的学生管理系统
  8. 新会计准则——新增固定资产可以当月计提折旧
  9. Pixhawk学习笔记(5)——PX4FLOW光流传感器调试过程记录
  10. VBA中byref类型不匹配 ByRef Argument Type Mismatch错误