LeetCode——752. 打开转盘锁

news2024/10/6 2:06:33

一、题目

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

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

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

字符串 target 代表可以解锁的数字,你需要给出解锁需要的最小旋转次数,如果无论如何不能解锁,返回 -1 。
在这里插入图片描述
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/open-the-lock/description/

二、C++解法

我的思路及代码

采用BFS,当前状态到下一个状态无非就是4个位置往上拨,或者下拨。那么把这个状态抽象为一张图,即是从根节点出发有8个子节点的多叉树,最后我们要找的target就在其中某个结点。因为要找到最短的路径,所以我们采用BFS齐头并进的办法。由于题目中提到了 deadends 所以我们可以采用一组哈希表来存储 deadends 同时来记录我们已经访问到的组合,以免走回头路。具体代码如下。

class Solution {
public:
    void plusOne(string &ans,int index){
        if(ans[index] == '9')
        ans[index] = '0';
        else ans[index]++;
    }

    void minusOne(string &ans,int index){
        if(ans[index] == '0')
        ans[index] = '9';
        else ans[index]--;
    }

    int openLock(vector<string>& deadends, string target) {
        if(target == "0000")
        return 0;
        queue<string> q;
        unordered_map<string,bool> map;
        for(int k=0;k<deadends.size();k++){
            if(deadends[k]=="0000")
            return -1;
            else{
                map[deadends[k]] = true;
            }
        }
        q.push("0000");
        int ans=0;
        string s1,s2;
        map["0000"] = true;

        while(q.size()){
            int size = q.size();
            ans++;
            for(int i=0;i<size;i++){      
                for(int j=0;j<4;j++){
                    s1 = q.front();
                    plusOne(s1,j);
                    if(s1==target)
                    return ans;
                    if(!map[s1]){
                        map[s1]=true;
                        q.push(s1);
                    }
                } 

                for(int j=0;j<4;j++){
                    s2 = q.front();
                    minusOne(s2,j);
                    if(s2==target)
                    return ans;
                    if(!map[s2]){
                        map[s2]=true;
                        q.push(s2);
                    }
                }
                q.pop();
            }
        }
        return -1;
    }
};

在这里插入图片描述

官方参考代码

启发式搜索

在这里插入图片描述
在这里插入图片描述

struct AStar {
    // 计算启发函数
    static int getH(const string& status, const string& target) {
        int ret = 0;
        for (int i = 0; i < 4; ++i) {
            int dist = abs(int(status[i]) - int(target[i]));
            ret += min(dist, 10 - dist);
        }
        return ret;
    };

    AStar(const string& status, const string& target, int g): status_{status}, g_{g}, h_{getH(status, target)} {
        f_ = g_ + h_;
    }

    bool operator< (const AStar& that) const {
        return f_ > that.f_;
    }

    string status_;
    int f_, g_, h_;
};

class Solution {
public:
    int openLock(vector<string>& deadends, string target) {
        if (target == "0000") {
            return 0;
        }

        unordered_set<string> dead(deadends.begin(), deadends.end());
        if (dead.count("0000")) {
            return -1;
        }

        auto num_prev = [](char x) -> char {
            return (x == '0' ? '9' : x - 1);
        };
        auto num_succ = [](char x) -> char {
            return (x == '9' ? '0' : x + 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;
        };

        priority_queue<AStar> q;
        q.emplace("0000", target, 0);
        unordered_set<string> seen = {"0000"};

        while (!q.empty()) {
            AStar node = q.top();
            q.pop();
            for (auto&& next_status: get(node.status_)) {
                if (!seen.count(next_status) && !dead.count(next_status)) {
                    if (next_status == target) {
                        return node.g_ + 1;
                    }
                    q.emplace(next_status, target, node.g_ + 1);
                    seen.insert(move(next_status));
                }
            }
        }

        return -1;
    }
};

启发式搜索不讨论时空复杂度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/363352.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python每日一练(20230222)

目录 1. 柱状图中最大的矩形 2. 汇总区间 3. 寻找旋转排序数组中的最小值 1. 柱状图中最大的矩形 难度&#xff1a;困难 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出…

IDEA工具系列之连接Linux

我们在开发的时候&#xff0c;用IDEA开发程序&#xff0c;用XSHELL来管理服务器&#xff0c;这两个工具切换比较麻烦。有没有用IDEA来连接Linux。当然有&#xff0c;下面有实践步骤&#xff1a; 首先&#xff1a;连接Linux 打开IDEA->Tools->Start SSH Session 其中1&…

MySQL------窗口函数

一、窗口函数定义 1、 适用场景及分类 怎么样得到各部门工资排名前N名员工列表? 查找各部门每人工资占部门总工资的百分比&#xff1f; 累计求和如何计算&#xff1f; 连续统计N天登陆的用户&#xff1f;以上类型问题均使用窗口函数可以解决&#xff0c;这类需求都有一个共同…

51单片机串口使用

文章目录前言一、串口概念二、中断中的RI、TI和SUBF1.RI2.TI3.SUBF三、串口波特率的计算四、代码的编写总结前言 今天将为大家讲解51单片机的串口原理及代码编写。 一、串口概念 51单片机串口是一种通信接口&#xff0c;它可以将51单片机与外部设备连接起来&#xff0c;实现…

单片机输入输出模式

单片机输入输出模式输入模式模拟输入、浮空输入、上拉输入、下拉输入GPIO输出模式推挽输出、开漏输出、复用推挽输出、复用开漏输出。上下拉电阻上拉电阻下拉电阻输入模式 模拟输入、浮空输入、上拉输入、下拉输入 模拟输入&#xff1a;I/O端口的模拟信号&#xff08;电压信号…

Python入门自学进阶-Web框架——32、上课、作业流程开发

对学员上课、作业进行管理。首先对几个表&#xff0c;即model用途进行阐述&#xff1a;课程表存放要开什么课&#xff0c;有了课程表&#xff0c;就要有班级&#xff0c;如开了Python入门课程&#xff0c;再根据学员人数&#xff0c;组成班级&#xff0c;如Python入门课程一班、…

报考浙大MBA项目的基本常识信息

一、项目简介 以培养具有国际视野、创新创业精神、卓越领导能力和高度社会责任感的中高级管理人才和创业型人才为己任。通过对引领时代发展的经典管理思想和前沿管理理念的传授&#xff0c;以及对推动行业健康发展的企业管理实践的研讨&#xff0c;来培养和提升学员的职业意…

一个测试工程师的7年感悟 ---- 致在一路独行的你(别放弃)

前言 不知不觉在软件测试行业&#xff0c;摸爬滚打了7年之久。这一路上也留下了许许多多令我难以忘记的故事。有刚入行时的迷茫&#xff0c;有学习技术路上踩过的坑&#xff0c;有做项目连夜敲代码的悲情也有迎来项目成功上线的欢愉&#xff0c;有太多太多值得铭记的瞬间&…

JUC-day02

JUC-day02 集合的线程安全callable和futureJUC三个工具类(练习)读写锁: 共享锁 独占锁(练习)AQS: 实现原理(核心方法)CAS: 原理–>可见性关键字 1 集合的线程安全(重点) 1.1 集合操作Demo NotSafeDemo public static void main(String[] args) {List list new ArrayLis…

Java集合(二)---Map

1.什么是Hash算法哈希算法是指把任意长度的二进制映射为固定长度的较小的二进制值&#xff0c;这个较小的二进制值叫做哈希值static final int hash(Object key) {int h;return (key null) ? 0 : (h key.hashCode()) ^ (h >>> 16);}以上是HashMap中的hash算法代码2…

三天吃透Spring面试八股文(最新整理)

本文已经收录到Github仓库&#xff0c;该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点&#xff0c;欢迎star~ Github地址&#xff1a;https://github.com/…

【音视频处理】为什么MP3不是无损音乐?音频参数详解,码率、采样率、音频帧、位深度、声道、编码格式的关系

大家好&#xff0c;欢迎来到停止重构的频道。上期我们讨论了视频的相关概念&#xff0c;本期我们讨论音频的相关概念。包括采样率、码率、单双声道、音频帧、编码格式等概念。这里先抛出一个关于无损音频的问题。为什么48KHz采样率的.mp3不是无损音乐 &#xff0c;而48KHz采样率…

95后刚毕业2、3年就年薪50W,才发现,打败我们的不是年龄····

一刷朋友圈&#xff0c;一读公众号&#xff0c;一打开微博&#xff0c;甚至是一和朋友聊天&#xff0c;这些让人焦虑的话题总会铺天盖地的袭来&#xff1a; Ta刚毕业半年&#xff0c;就升职加薪当上了测试主管 &#xff08;同样是一天24小时&#xff0c;为什么同龄人正在抛弃…

【Linux】编辑器——vim(最小集+指令集+自动化配置)

目录 1.vim最小集 1.1 vim的三种模式 1.2 vim的基本操作 2.vim指令集 2.1 命令模式指令集 移动光标 删除文字 复制 替换 撤销上一次操作 更改 跳至指定的行 2.2 底行模式指令集 列出行号 跳到文件中的某一行 查找字符 保存文件 多文件操作 3.如何配置vim 配…

网络编程之TCP 的介绍

TCP 的介绍学习目标能够说出TCP 的特点1. 网络应用程序之间的通信流程之前我们学习了 IP 地址和端口号&#xff0c;通过 IP 地址能够找到对应的设备&#xff0c;然后再通过端口号找到对应的端口&#xff0c;再通过端口把数据传输给应用程序&#xff0c;这里要注意&#xff0c;数…

科技 “新贵”ChatGPT 缘何 “昙花一现” ,仅低代码风靡至今

恍惚之间&#xff0c;ChatGPT红遍全网&#xff0c;元宇宙沉入深海…… 在科技圈&#xff0c;见证了太多“昙花一现”&#xff0c;“新贵” ChatGPT 的爆火几乎复制了元宇宙的路径&#xff0c;它会步元宇宙的后尘&#xff0c;成为下一个沉入深海的工具吗&#xff1f; 不可否认的…

小程序开发注意点

1.组件样式隔离注意点 2.methods方法 3.自定义组件的properties参数 4.自定义组件的事件监听 5.纯数据字段 6.插槽 单个插槽 启用多插槽 使用多个插槽 7.属性绑定实现父传子功能 例如在这里有一个组件为<one></one>&#xff0c;那么可以在组件当中传入参数 &l…

iOS上架及证书最新创建流程

目前使用uniapp框架开发app&#xff0c;大大节省了我们兼容多端应用的工作量和人手&#xff0c;所以目前非常缺乏ios上架和证书创建流程流程的文档假如你没有任何的打包或上架经验&#xff0c;参考本文有很大的收益。通常申请ios证书和上架ipa应用&#xff0c;是需要MAC电脑的&…

干货复试详细教程——从联系导师→自我介绍的复试教程

文章目录联系导师联系之前的准备联系导师注意自我介绍教育技术领域通用的复试准备其他补充联系导师 确定出分和自己能进复试以后联系。 分两类 科研技能型 低调&#xff0c;如实介绍&#xff0c;不吹不水。就算你很牛啥都会手握核心期刊论文也不太狂 学霸高分型 不要自卑&…

审计syslog设备活动

从交换机到路由器&#xff0c;几乎所有网络设备都会生成syslog。因为您的网络中有大量生成syslog的设备&#xff0c;所以审计过程&#xff08;包括跟踪、监控和分析所有syslog&#xff09;需要花费大量时间和精力。但是&#xff0c;无论这些任务需要多少精力去完成&#xff0c;…