由于这个问题,涉及了很多知识,例如数据结构里面的哈希表,c++中的迭代器,因此,需要对于每一个疑惑逐一击破。

问题描述

You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'. The wheels can rotate freely and wrap around: for example we can turn '9' to be '0', or '0' to be '9'. Each move consists of turning one wheel one slot.

The lock initially starts at '0000', a string representing the state of the 4 wheels.

You are given a list of deadends dead ends, meaning if the lock displays any of these codes, the wheels of the lock will stop turning and you will be unable to open it.

Given a target representing the value of the wheels that will unlock the lock, return the minimum total number of turns required to open the lock, or -1 if it is impossible.

Example 1:

Input: deadends = ["0201","0101","0102","1212","2002"], target = "0202"
Output: 6
Explanation:
A sequence of valid moves would be "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202".
Note that a sequence like "0000" -> "0001" -> "0002" -> "0102" -> "0202" would be invalid,
because the wheels of the lock become stuck after the display becomes the dead end "0102".

Example 2:

Input: deadends = ["8888"], target = "0009"
Output: 1
Explanation:
We can turn the last wheel in reverse to move from "0000" -> "0009".

Example 3:

Input: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
Output: -1
Explanation:
We can't reach the target without getting stuck.

Example 4:

Input: deadends = ["0000"], target = "8888"
Output: -1

Note:

  1. The length of deadends will be in the range [1, 500].
  2. target will not be in the list deadends.
  3. Every string in deadends and the string target will be a string of 4 digits from the 10,000 possibilities '0000' to '9999'.

参考答案

 class Solution {
public:
int openLock(vector<string>& deadends, string target) {
unordered_set<string> deadlock(deadends.begin(), deadends.end());
if (deadlock.count("")) return -;
int res = ;
unordered_set<string> visited{{""}};
queue<string> q{{""}};
while (!q.empty()) {
++res;
for (int k = q.size(); k > ; --k) {
auto t = q.front(); q.pop();
for (int i = ; i < t.size(); ++i) {
for (int j = -; j <= ; ++j) {
if (j == ) continue;
string str = t;
str[i] = ((t[i] - '') + + j) % + '';
if (str == target) return res;
if (!visited.count(str) && !deadlock.count(str)) q.push(str);
visited.insert(str);
}
}
}
}
return -;
}
};

补充知识

迭代器

正如我们知道的,程序中包含了大量的迭代,这些迭代都是在循环中进行的,比如for。

迭代(Iteration):是一种行为,对于某个特定容器,进行遍历的行为。

可迭代对象(Iterable):是一个容器,例如set,list,vector等等,一堆数据装在里面,而这个容器可以进行迭代操作。

那什么是迭代器(iterator)呢?

迭代器,就好像是一个可以供人们操作的装置对象,其中包含了数据,以及可以进行操作的按钮(例如c++中的begin,end等等[1]),这样我们可以很方便的使用并且操作打包好的数据。

另外还有一个问题,比如下面这个例子[2]:

std::vector<int> v;
for (vector<int>::iterator iter = v.begin(); iter != v.end(); ++iter)
{
// do someting with iter
}

v 能懂,是一个vector。vector<int> 类型的 iterator 也可以懂,但什么是 v.begin() ?

[1] 的解释是返回幵始迭代器。what the fxxk? 什么是开始迭代器?难道迭代器不是可以操纵的对象么?我查了很多的中文网站和博客,似乎都没有很理想的解释。后来查到了它的英文解释:begin() function is used to return an iterator pointing to the first element of the vector container.

这样就清楚好多了, v.begin() 是一个迭代器,特殊的是,它是指向容器中第一个元素的迭代器。

另外,也要注意 v.end() ,它也是迭代器,但它是 指向容器最后元素的 下一个位置的 迭代器。

使用例子[3]

#include <iostream>
#include <vector>
using namespace std; int main()
{
// declaration of vector container
vector<int> myvector{ , , , , }; // using end() to print vector
for (auto it = myvector.begin() ; it != myvector.end(); ++it)
cout << ' ' << *it;
return ;
}

输出为:

1 2 3 4 5

另外,不用费心考虑iteator的类型,直接使用auto即可

 

insert & find

使用迭代器的好处,就是可以使用一堆提供好的函数,这个例子中可以找到 insert 和 find 。
方式就如答案所示,详细的可以参看:http://c.biancheng.net/view/570.html
 

t[i] - '0' 是个什么?

第17行,出现了 str[i] = (( t[i] - '0' ) + 10 + j) % 10 + '0' 这一行,所以我陷入了迷思,为什么string类型可以进行运算。后来通过print进行测试。
发现,如果对'0'进行加减操作,会出现这样的结果。
运行如下代码:
 #include <iostream>
#include <string> using namespace std; int main()
{
string str = "";
string result ;
for(int i = -; i<;i++){
result[] = str[] + i;
cout<<result<<endl;
} return ;
}

可以得到:

'
(
)
+
,
.
/

我们会发现,直接对 string 进行加减操作,直接会显示上一个字符和之后的字符。因此,17行源代码的意思是:

减去‘0’,即获得原来的 t[i] 对于‘0’的偏移量,这是一个 int 类型。基于该偏移量,进行加减1的操作(+j),然后再次添加‘0’,将偏移量变成 string 类型。而 +10 和 %10 操作,为了防止 0-1 = -1 操作的发生,或者是 9+1 = 10 的情况发生。-1对应着 9 (9 = 0+10-1),而 10 对应着 0 (0 = 9+1 +10 对 10 取余是 0)。

很舒服。

[1]: http://c.biancheng.net/view/409.html

[2]:https://qinglinmao8315.github.io/c++/2018/03/07/how-std-vector-end-work.html

[3]: https://www.geeksforgeeks.org/vectorbegin-vectorend-c-stl/

LC 752 Open the Lock的更多相关文章

  1. LeetCode 752. Open the Lock

    原题链接在这里:https://leetcode.com/problems/open-the-lock/ 题目: You have a lock in front of you with 4 circ ...

  2. [LeetCode] 752. Open the Lock 开锁

    You have a lock in front of you with 4 circular wheels. Each wheel has 10 slots: '0', '1', '2', '3', ...

  3. 【LeetCode】752. Open the Lock 解题报告(Python & C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 日期 题目地址:https://leetcode.c ...

  4. golang锁

    golang锁包:https://studygolang.com/pkgdoc sync.Mutex是一个互斥锁 var lock sync.Mutex 加锁段在中 lock.lock() lock. ...

  5. LeetCode All in One题解汇总(持续更新中...)

    突然很想刷刷题,LeetCode是一个不错的选择,忽略了输入输出,更好的突出了算法,省去了不少时间. dalao们发现了任何错误,或是代码无法通过,或是有更好的解法,或是有任何疑问和建议的话,可以在对 ...

  6. 算法与数据结构基础 - 广度优先搜索(BFS)

    BFS基础 广度优先搜索(Breadth First Search)用于按离始节点距离.由近到远渐次访问图的节点,可视化BFS 通常使用队列(queue)结构模拟BFS过程,关于queue见:算法与数 ...

  7. leetcode 学习心得 (4)

    645. Set Mismatch The set S originally contains numbers from 1 to n. But unfortunately, due to the d ...

  8. All LeetCode Questions List 题目汇总

    All LeetCode Questions List(Part of Answers, still updating) 题目汇总及部分答案(持续更新中) Leetcode problems clas ...

  9. LeetCode All in One 题目讲解汇总(转...)

    终于将LeetCode的免费题刷完了,真是漫长的第一遍啊,估计很多题都忘的差不多了,这次开个题目汇总贴,并附上每道题目的解题连接,方便之后查阅吧~ 如果各位看官们,大神们发现了任何错误,或是代码无法通 ...

随机推荐

  1. Python相关分析—一个金融场景的案例实操

    哲学告诉我们:世界是一个普遍联系的有机整体,现象之间客观上存在着某种有机联系,一种现象的发展变化,必然受与之关联的其他现象发展变化的制约与影响,在统计学中,这种依存关系可以分为相关关系和回归函数关系两 ...

  2. Pytest学习笔记(三) 在代码中运行pytest

    前面介绍的是在cmd中执行pytest,平常我们一般都是通过编译器(如pycharm)来编写用例的,写完用例后,需要调试看看是否能运行,如果每次都切换到cmd中执行,太麻烦. 因此,这一节来说下怎么在 ...

  3. 单调队列优化DP——习题收集

    前言 感觉可以用单调队列优化dp的模型还是挺活的,开个随笔记录一些遇到的比较有代表性的模型,断续更新.主要做一个收集整理总结工作. 记录 0x01 POJ - 1821 Fence,比较适合入门的题, ...

  4. 部署Hadoop2.0高性能集群

    废话不多说直接实战,部署Hadoop高性能集群: 拓扑图: 一.实验前期环境准备: 1.三台主机配置hosts文件:(复制到另外两台主机上) [root@tiandong63 ~]# more /et ...

  5. 【洛谷4251】 [SCOI2015]小凸玩矩阵(二分答案,二分图匹配)

    题面 传送门 Solution 看到什么最大值最小肯定二分啊. check直接跑一个二分图匹配就好了. orz ztl!!! 代码实现 /* mail: mleautomaton@foxmail.co ...

  6. iOS (APP)进程间8中常用通信方式总结

    1 URL Scheme 2 Keychain 3 UIPasteboard 4 UIDocumentInteractionController 5 local socket 6 AirDrop 7 ...

  7. centos 下 安装vim

    我们在安装完Centos后,它默认的是安装了VI编辑器,VIM是没有安装的,所以我们在使用vim test.txt时会提示: vim command not found ... 这就是说明我们的Lin ...

  8. ORA-00054: 资源正忙 --锁表的解决方法

    问题描述 ORA-00054: 资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效 发生异常 原因:其他Session已经对目标表做了操作,且未提交操作,导致锁表,新的Session无法 ...

  9. JAVA字符串处理函数列表一览

    JAVA字符串处理函数列表一览   Java中的字符串也是一连串的字符.但是与许多其他的计算机语言将字符串作为字符数组处理不同,Java将字符串作为String类型对象来处理.将字符串作为内置的对象处 ...

  10. CefGlue获取网页源代码

    1.编写一个CefStringVisitor类: public class MyStringVisitor : CefStringVisitor { private readonly TaskComp ...