您的位置:首页 > 游戏 > 手游 > 夜夜夜在线观看_特价服务器_公司宣传推广方案_南宁seo推广

夜夜夜在线观看_特价服务器_公司宣传推广方案_南宁seo推广

2025/4/21 21:55:10 来源:https://blog.csdn.net/2301_76324845/article/details/147025653  浏览:    关键词:夜夜夜在线观看_特价服务器_公司宣传推广方案_南宁seo推广
夜夜夜在线观看_特价服务器_公司宣传推广方案_南宁seo推广

核心考点:广度优先搜索 (BFS)、哈希表、字符串

知识点补充:【语法】结构化绑定

题目描述

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' 。每个拨轮可以自由旋转:例如把 '9' 变为 '0''0' 变为 '9' 。每次旋转都只能旋转一个拨轮的一位数字。

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

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

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

【测试用例见文末】

题目详解:

class Solution {
public:int openLock(vector<string>& deadends, string target) {// 如果目标是"0000",直接返回0,因为已经解锁if (target == "0000") {return 0;}// 将死亡数字集合转为哈希表,方便查询unordered_set<string> dead(deadends.begin(), deadends.end());// 如果初始状态 "0000" 就是死亡数字,返回 -1if (dead.count("0000")) {return -1;}// 定义辅助函数,获取当前数字的前一个数字auto num_prev = [](char x) -> char {return (x == '0' ? '9' : x - 1);  // '0' -> '9', 其他字符减去 1};// 定义辅助函数,获取当前数字的后一个数字auto num_succ = [](char x) -> char {return (x == '9' ? '0' : x + 1);  // '9' -> '0', 其他字符加 1};// 获取当前状态转动一个拨轮后的所有可能状态auto get = [&](string& status) -> vector<string> {vector<string> ret;for (int i = 0; i < 4; ++i) {  // 遍历每个拨轮char num = status[i];  // 获取当前拨轮的数字status[i] = num_prev(num);  // 尝试前一个数字ret.push_back(status);  // 添加到结果中status[i] = num_succ(num);  // 尝试后一个数字ret.push_back(status);  // 添加到结果中status[i] = num;  // 恢复原状态}return ret;};// 使用队列进行 BFS 搜索,队列中保存当前状态和步数queue<pair<string, int>> q;q.emplace("0000", 0);  // 从初始状态开始,步数为 0unordered_set<string> seen = {"0000"};  // 用哈希集合记录已经访问过的状态// BFS 循环while (!q.empty()) {auto [status, step] = q.front();  // 获取当前状态和步数q.pop();// 枚举当前状态可以转动到的所有新状态for (auto&& next_status: get(status)) {// 如果新状态未被访问过且不在死亡数字中if (!seen.count(next_status) && !dead.count(next_status)) {// 如果新状态是目标状态,返回当前步数 + 1if (next_status == target) {return step + 1;}// 否则将新状态加入队列,步数 + 1,并标记为已访问q.emplace(next_status, step + 1);seen.insert(next_status);}}}// 如果队列为空,说明无法到达目标状态return -1;}
};

语法补充:

1.结构化绑定

Structured Binding)它用于从 pair(或 tuple)等类型中直接解包多个值。这个语法是在 C++17 引入的。 

auto [status, step] = q.front();

相当于,可以简化代码:

pair<string, int> p = q.front();  // 取出队首元素
string status = p.first;  // 获取状态
int step = p.second;  // 获取步数

2.辅助函数:Lambda函数

具体可看文章:【C++基础】Lambda 函数 基础知识讲解学习及难点解析-CSDN博客

思路分析:

  1. 题目分析:  这道题目本质上是一个状态转移问题,可以通过广度优先搜索(BFS)来解决。每个锁的状态可以视作一个图的节点,状态之间的转移(旋转拨轮)是图中的边,目标是从初始状态 "0000" 通过最少的操作到达目标状态 target。同时,要避免经过 deadends 中的状态,这些状态会将锁永久锁定。

  2. 基本思路

    • 如果目标状态是 "0000",直接返回 0,因为已经解锁。

    • 使用 BFS,从 "0000" 状态开始进行层级遍历,每次可以选择转动一个拨轮到相邻状态(前进或后退一位)。

    • 对于每个状态,检查它是否是 deadends 中的状态,如果是则跳过;如果不是,则加入队列继续搜索。

    • 如果到达目标状态 target,返回当前步数(即最小旋转次数)。

    • 如果队列为空,说明无法到达目标状态,返回 -1。

  3. 细节考虑

    • 使用 unordered_set 来存储 deadends 和已经访问过的状态,避免重复计算。

    • 定义了两个辅助函数 num_prevnum_succ 用于计算每次旋转的前一个或后一个数字。

    • 通过 get 函数生成当前状态的所有可达状态(即转动一个拨轮后可能的状态)。

  4. 时间和空间复杂度

    • 时间复杂度:BFS 搜索的时间复杂度是 O(N),其中 N 是状态空间的大小。由于每个拨轮有 10 个数字,四个拨轮的总状态数为 104=1000010^4 = 10000104=10000,所以时间复杂度是 O(10000)。

    • 空间复杂度:BFS 的空间复杂度是 O(N),需要存储队列和已访问的状态,最大空间复杂度为 O(10000)。

测试用例:

示例 1:

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

示例 2:

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

示例 3:

输入: deadends = ["8887","8889","8878","8898","8788","8988","7888","9888"], target = "8888"
输出:-1
解释:无法旋转到目标数字且不被锁定。

提示:

  • 1 <= deadends.length <= 500

  • deadends[i].length == 4

  • target.length == 4

  • target 不在 deadends 之中

  • target 和 deadends[i] 仅由若干位数字组成

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com