LeetCode,转盘锁,set,queue

转盘锁

问题描述

你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: ‘0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’ 。每个拨轮可以自由旋转:例如把 ‘9’ 变为 ‘0’,‘0’ 变为 ‘9’ 。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为 ‘0000’ ,一个代表四个拨轮的数字的字符串。
列表 deadends 包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target 代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。
示例 1:

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

示例二:

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

编程思路及代码实现

要制定合理的搜索策略:对10000个情况进行分类:

  1. 使用带有哈希集的广度优先搜索
  2. 每一次每个拨轮+1或者-1
  3. 添加的新数不能在先前出现过且不在死亡序列中
  4. 注意“0000”在死亡序列中的特殊情况
    代码实现:
class Solution {
public:
    int openLock(vector<string>& deadends, string target) {
        queue<string> Myqueue;          // 用于存储节点的队列
        unordered_set<string> used;   //  存储已经遍历过的节点
        unordered_set<string> deadlocks(deadends.begin(),deadends.end());  // 存储所有的死亡序列
        int step{0};   //  初始化步数计数器
        vector<int> directs{-1,1};  // 拨轮+1或者-1
        Myqueue.push("0000");   // 将初始结点入队
        used.insert("0000");  
        if (deadlocks.count("0000"))  {    //针对初始节点 “0000”在死亡序列中的特殊情况进行判断
            return -1;
        }
        string cur;
        while(!Myqueue.empty()) {     // 广度优先搜索主循环(循环终止条件为队列为空)
            int size = Myqueue.size();  
            for (int i=0 ; i < size ; i++)  {
                cur=Myqueue.front();
                Myqueue.pop();
                if (cur==target) {
                    return step;
                }
                if (deadlocks.count((cur)))  {
                    continue;
                }
                for (int j=0 ; j<cur.size() ; j++)  {
                    for (auto direct:directs)  {
                        string change;
                        change=cur;
                        change[j]=((cur[j]-'0')+10+direct)%10+'0';
                        if (used.count(change)||deadlocks.count(change))  {
                            continue;
                        }
                        Myqueue.push(change);
                        used.insert(change);
                    }
                }
            }
            step = step + 1;
        }
        return -1;
    }
};

涉及到的C++知识
C++中的set

  • 概念:set作为一个容器用来存储同一数据类型的数据,并且能从一个数据集合中取出数据,在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。应该注意的是set中元素的值不能直接被改变
    unordered_set描述大体如下:无序集合容器(unordered_set)是一个存储唯一(unique,即无重复)的关联容器(Associative container),容器中的元素无特别的秩序关系,该容器允许基于值的快速元素检索,同时也支持正向迭代。 在一个unordered_set内部,元素不会按任何顺序排序,而是通过元素值的hash值将元素分组放置到各个槽(Bucker,也可以译为“桶”),这样就能通过元素值快速访问各个对应的元素(均摊耗时为O(1))。
  • 粗略理解:就是一个装东西的容器,但是放进去的东西不能重复,可以通过这个东西的值对其进行检索。
  • 一些操作:(这里给的是set的相关操作)在本题中使用了count()。
begin();            // 返回指向第一个元素的迭代器
end();              // 返回指向最后一个元素的迭代器
clear();            // 清除所有元素
count();            // 返回某个值元素的个数
 
empty();            // 如果集合为空,返回true
 
equal_range();      //返回集合中与给定值相等的上下限的两个迭代器
 
erase()–删除集合中的元素
 
find()–返回一个指向被查找到元素的迭代器
 
get_allocator()–返回集合的分配器
 
insert()–在集合中插入元素
 
lower_bound()–返回指向大于(或等于)某值的第一个元素的迭代器
 
key_comp()–返回一个用于元素间值比较的函数
 
max_size()–返回集合能容纳的元素的最大限值
 
rbegin()–返回指向集合中最后一个元素的反向迭代器
 
rend()–返回指向集合中第一个元素的反向迭代器
 
size()–集合中元素的数目
 
swap()–交换两个集合变量
 
upper_bound()–返回大于某个值元素的迭代器
 
value_comp()–返回一个用于比较元素间的值的函数

C++中的queue
队列是C++中先入先出的数据结构,会用于广度优先搜索,以下是其基本操作:

.push() -入队,在队列后面添加一个成员
.pop() - 出队
.front() - 返回队列中头部成员
.back() - 返回队列中尾部成员
.size() - 返回队列中元素个数

其他用到的操作

string.size() - 返回字符串中的字符数
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
校园悬赏任务平台对字典管理、论坛管理、任务资讯任务资讯公告管理、接取用户管理、任务管理、任务咨询管理、任务收藏管理、任务评价管理、任务订单管理、发布用户管理、管理员管理等进行集中化处理。经过前面自己查阅的网络知识,加上自己在学校课堂上学习的知识,决定开发系统选择小程序模式这种高效率的模式完成系统功能开发。这种模式让操作员基于浏览器的方式进行网站访问,采用的主流的Java语言这种面向对象的语言进行校园悬赏任务平台程序的开发,在数据库的选择上面,选择功能强大的Mysql数据库进行数据的存放操作。校园悬赏任务平台的开发让用户查看任务信息变得容易,让管理员高效管理任务信息。 校园悬赏任务平台具有管理员角色,用户角色,这几个操作权限。 校园悬赏任务平台针对管理员设置的功能有:添加并管理各种类型信息,管理用户账户信息,管理任务信息,管理任务资讯公告信息等内容。 校园悬赏任务平台针对用户设置的功能有:查看并修改个人信息,查看任务信息,查看任务资讯公告信息等内容。 系统登录功能是程序必不可少的功能,在登录页面必填的数据有两项,一项就是账号,另一项数据就是密码,当管理员正确填写并提交这二者数据之后,管理员就可以进入系统后台功能操作区。项目管理页面提供的功能操作有:查看任务,删除任务操作,新增任务操作,修改任务操作。任务资讯公告信息管理页面提供的功能操作有:新增任务资讯公告,修改任务资讯公告,删除任务资讯公告操作。任务资讯公告类型管理页面显示所有任务资讯公告类型,在此页面既可以让管理员添加新的任务资讯公告信息类型,也能对已有的任务资讯公告类型信息执行编辑更新,失效的任务资讯公告类型信息也能让管理员快速删除。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值