LeetCode 752.打开转盘锁 - C++ - 广度优先搜索(BFS)

题目:打开转盘锁

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有 10 个数字:‘0’到’9’。每个拨轮可以自由旋转:例如把’9’变为’0’,‘0’变为’9’。每次旋转都只能旋转一个拨轮的一位数字。

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

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

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

示例:

输入:deadends=["8888"],target="0009"
输出:1
解释:把最后一位反向旋转一次即可"0000"->"0009"。

提示:

  1. 死亡列表 deadends 的长度范围为[1,500]。
  2. 目标数字 target 不会在 deadends 之中。
  3. 每个 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

扫描二维码关注公众号,回复: 11399538 查看本文章

猜你喜欢

转载自blog.csdn.net/Aelous_dp/article/details/107481336