由于这个问题,涉及了很多知识,例如数据结构里面的哈希表,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. JVM GC之垃圾收集算法

    1.垃圾收集概念 GC目的 分配内存,为每个新建的对象分配空间 确保还在使用的对象的内存一直还在,不能把有用的空间当垃圾回收了 释放不再使用的对象所占用的空间 我们把还被引用的对象称为活的,把不再被引 ...

  2. golang 文件导入数据追加sheet

    func ReadXlsx(c []CmdbTest, SheetName string) error {     //打开文件,如果文件不存在创建,存在就打开     path := ". ...

  3. python+selenium 切换至iframe

    方法一: from selenium import webdriver driver = webdriver.Firefox() driver.switch_to.frame(0) # 1.用fram ...

  4. PHPStorm2017去掉函数参数提示

    今天升级到 PHPStorm 2017.1 发现增加了好些新功能, 有个默认开启的参数名和类型提示功能, 虽然功能挺强大的, 不过我用不着, 还是关掉的好, 有同样需求的同学可以看看 例子比较特殊这么 ...

  5. Elasticsearch6.5.1破解x-pack,设置密码并使用head插件登陆。

    #没有许可证的es无法持久的设置密码,而且使用一段时间后会过期,过期后,一些功能无法被使用,例如head插件无法看到es状态. 下图是过期的es的状态,可通过此url查看:http://ip:port ...

  6. pi币--π币--手机离线式挖矿软件--pi中文教程!

    Pi Network派型网络,国外热度很高手机移动式挖矿软件 一个新出的手机移动式挖矿软件,在国外热度很高,国内玩的人目前很少.项目团队成员均来自斯坦福大学,三个创始人斯坦福博士教授,现在处于挖矿第一 ...

  7. Selenium 2自动化测试实战37(自动发邮件功能)

    自动发邮件功能 例如,如果想在自动化脚本运行完成之后,邮箱就可以收到最新的测试报告结果.SMTP(Simple Mail Transfer Protocol)是简单邮件传输协议,它是一组用于由源地址到 ...

  8. Java 泛型,你了解类型擦除吗?

    泛型,一个孤独的守门者. 大家可能会有疑问,我为什么叫做泛型是一个守门者.这其实是我个人的看法而已,我的意思是说泛型没有其看起来那么深不可测,它并不神秘与神奇.泛型是 Java 中一个很小巧的概念,但 ...

  9. Hadoop集群参数和常用端口

    一.Hadoop集群参数配置 在hadoop集群中,需要配置的文件主要包括四个,分别是core-site.xml.hdfs-site.xml.mapred-site.xml和yarn-site.xml ...

  10. Centos7.2 搭建emqttd集群,添加自启动服务

    关闭防火墙(可选):systemctl stop firewalld.service 1.安装依赖库> sudo yum -y install make gcc gcc-c++ kernel-d ...