题目:打开转盘锁
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有 10 个数字:‘0’到’9’。每个拨轮可以自由旋转:例如把’9’变为’0’,‘0’变为’9’。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为’0000’,一个代表四个拨轮的数字的字符串。
列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回-1。
示例:
输入:deadends=["8888"],target="0009"
输出:1
解释:把最后一位反向旋转一次即可"0000"->"0009"。
提示:
- 死亡列表 deadends 的长度范围为[1,500]。
- 目标数字 target 不会在 deadends 之中。
- 每个 deadends 和 target 中的字符串的数字会在 10000 个可能的情况’0000’到’9999’中产生。
代码如下(C++):
class Solution {
public:
int turnToNumber(string a){ // 将数字字符串转变为纯数字
int a = a[0]; // 个十百千,分别减去 '0' 变为数字。
int b = a[1];
int c = a[2];
int d = a[3];
int res = (a - '0') * 1000 + (b - '0') * 100 + (c - '0') * 10 + (d - '0');
return res;
}
int openLock(vector<string>& deadends, string target) { // 开锁
string input = "0000";
unordered_set<string> deadset(deadends.begin(),deadends.end()); // 无序set
if(deadset.count(input)) return -1; // 如果deadend内部有‘0000’,直接return -1
queue<string> q; // 定义队列q
bool visited[10000];
memset(visited,0,sizeof(visited)); // 标记是否被访问过
visited[0] = true;
q.push("0000");
int count = 0;
while(!q.empty()){ // 只要队列不为空,就一直索引
count++;
int size = q.size();
for(int i = 0; i < size;i++){ // 判断队列中的每一串数字
string s = q.front();
for(int i = 0; i < 4; i++){
for(auto step:{-1,1}){ // 都+1或-1,相当于一次 +1 一次 -1
string temp = s;
temp[i] = (temp[i]-'0' + step + 10) % 10 + '0';
if(temp == target) return count; // 如果是目标则返回count
if(!deadset.count(temp)&& visited[turnToNumber(temp)] == false){
q.push(temp); // 推入队列中
visited[turnToNumber(temp)] = true; // 标记为已经访问过
}
} // 若是deadend不做处理,不继续向下搜索,相当于绕过deadend
}
q.pop(); // q.front已经处理过,出列,更新q.front()
}
}
return -1;
}
};
memset 常用作初始化工作,void *memset(void *s, int ch, size_t n); 将 s 中当前位置后面的 n 个字节用 ch 替换并返回 s.
函数原型是 extern void *memset(void *buffer, int c, int count); buffer: 为指针或是数组,c: 是赋给 buffer 的值,count: 是 buffer 的长度。
官方 python 解答:看着挺简单,让人头大,记录一下。
class Solution(object):
def openLock(self, deadends, target):
def neighbors(node):
for i in xrange(4):
x = int(node[i])
for d in (-1,1): # 加减 1
y = (x + d) % 10
yield node[:i]+str(y) + node[i+1:]
dead = set(deadends)
queue = collections.deque([('0000',0)])
seen = {'0000'}
while queue: # 广度优先搜索
node, depth = queue.popleft()
if node == target: return depth
if node in dead: continue
for nei in neighbors(node):
if nei not in seen:
seen.add(nei)
queue.append((nei, depth+1))
return -1
放在最后
如果您喜欢我的文章,拜托点赞收藏关注,博主会根据大家喜好来推出相关系列文章~
更多精彩内容也可以访问我的博客Aelous-BLog