当前位置: 首页 > news >正文

【LeetCode每日一题】【2023/2/9】1797. 设计一个验证系统

文章目录

  • 1797. 设计一个验证系统
    • 方法1:哈希表
      • 代码总体


1797. 设计一个验证系统

LeetCode: 1797. 设计一个验证系统

中等\color{#FFB800}{中等}中等

你需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个新的验证码,这个验证码在 currentTime 时刻之后 timeToLive 秒过期。如果验证码被更新了,那么它会在 currentTime (可能与之前的 currentTime 不同)时刻延长 timeToLive 秒。

请你实现 AuthenticationManager 类:

  • AuthenticationManager(int timeToLive) 构造 AuthenticationManager 并设置 timeToLive 参数。
  • generate(string tokenId, int currentTime) 给定 tokenId ,在当前时间 currentTime 生成一个新的验证码。
  • renew(string tokenId, int currentTime) 将给定 tokenId未过期 的验证码在 currentTime 时刻更新。如果给定 tokenId 对应的验证码不存在或已过期,请你忽略该操作,不会有任何更新操作发生。
  • countUnexpiredTokens(int currentTime) 请返回在给定 currentTime 时刻,未过期 的验证码数目。

如果一个验证码在时刻 t 过期,且另一个操作恰好在时刻 t 发生(renew 或者 countUnexpiredTokens 操作),过期事件 优先于 其他操作。

示例 1:

在这里插入图片描述

输入:
["AuthenticationManager", "renew", "generate", "countUnexpiredTokens", "generate", "renew", "renew", "countUnexpiredTokens"]
[[5], ["aaa", 1], ["aaa", 2], [6], ["bbb", 7], ["aaa", 8], ["bbb", 10], [15]]
输出:
[null, null, null, 1, null, null, null, 0]解释:
AuthenticationManager authenticationManager = new AuthenticationManager(5); // 构造 AuthenticationManager ,设置 timeToLive = 5 秒。
authenticationManager.renew("aaa", 1); // 时刻 1 时,没有验证码的 tokenId 为 "aaa" ,没有验证码被更新。
authenticationManager.generate("aaa", 2); // 时刻 2 时,生成一个 tokenId 为 "aaa" 的新验证码。
authenticationManager.countUnexpiredTokens(6); // 时刻 6 时,只有 tokenId 为 "aaa" 的验证码未过期,所以返回 1 。
authenticationManager.generate("bbb", 7); // 时刻 7 时,生成一个 tokenId 为 "bbb" 的新验证码。
authenticationManager.renew("aaa", 8); // tokenId 为 "aaa" 的验证码在时刻 7 过期,且 8 >= 7 ,所以时刻 8 的renew 操作被忽略,没有验证码被更新。
authenticationManager.renew("bbb", 10); // tokenId 为 "bbb" 的验证码在时刻 10 没有过期,所以 renew 操作会执行,该 token 将在时刻 15 过期。
authenticationManager.countUnexpiredTokens(15); // tokenId 为 "bbb" 的验证码在时刻 15 过期,tokenId 为 "aaa" 的验证码在时刻 7 过期,所有验证码均已过期,所以返回 0 。

提示:

  • 1 <= timeToLive <= 10^8
  • 1 <= currentTime <= 10^8
  • 1 <= tokenId.length <= 5
  • tokenId 只包含小写英文字母。
  • 所有 generate 函数的调用都会包含独一无二的 tokenId 值。
  • 所有函数调用中,currentTime 的值 严格递增
  • 所有函数的调用次数总共不超过 2000 次。

方法1:哈希表

使用哈希表来存放验证码及其过期时间。哈希表的键为验证码字符串,值为对应的过期时间。

构造函数将 timeToLive 记录下来:

class AuthenticationManager
{
public:explicit AuthenticationManager(const int timeToLive): ttl{timeToLive} { }private:const int ttl;
};

函数 generate() 将传入的 tokenId 记录下来,并将 currentTime 加上 ttl 作为该验证码的 过期时间 记录下来:

void generate(string tokenId, const int currentTime)
{hashtable.emplace(std::move(tokenId), currentTime + ttl);
}

函数 renew() 实现验证码的更新。按题意,若哈希表中没有找到该验证码,则不做任何操作;若该验证码的过期时间 小于等于 当前时间 currentTime ,则删除,否则更新为 currentTime + ttl ,即在当前时间下 延后 ttl 个时间。

void renew(const string& tokenId, const int currentTime)
{if (const auto it = hashtable.find(tokenId);it != hashtable.end()){if (it->second > currentTime)it->second = currentTime + ttl;elsehashtable.erase(it);}
}

函数 countUnexpiredTokens 在调用函数 clearExpiredTokens 清除 过期 验证码后,返回哈希表中的元素个数,即为所求的当前 未过期 的验证码。

int countUnexpiredTokens(const int currentTime)
{clearExpiredTokens(currentTime);return static_cast<int>(hashtable.size());
}

函数 clearExpiredTokens 遍历哈希表,并逐个删除 过期的 验证码:

void clearExpiredTokens(const int currentTime)
{for (auto it = hashtable.begin(); it != hashtable.end();){if (const auto& [_, expireTime] = *it;expireTime <= currentTime)it = hashtable.erase(it);else++it;}
}

代码总体

#include <string>
#include <unordered_map>
using namespace std;class AuthenticationManager
{
public:explicit AuthenticationManager(const int timeToLive): ttl{timeToLive} { }void generate(string tokenId, const int currentTime){hashtable.emplace(std::move(tokenId), currentTime + ttl);}void renew(const string& tokenId, const int currentTime){if (const auto it = hashtable.find(tokenId);it != hashtable.end()){if (it->second > currentTime)it->second = currentTime + ttl;elsehashtable.erase(it);}}int countUnexpiredTokens(const int currentTime){clearExpiredTokens(currentTime);return static_cast<int>(hashtable.size());}private:void clearExpiredTokens(const int currentTime){for (auto it = hashtable.begin(); it != hashtable.end();){if (const auto& [_, expireTime] = *it;expireTime <= currentTime)it = hashtable.erase(it);else++it;}}private:const int ttl;unordered_map<string, int> hashtable;
};

复杂度分析:

  • 时间复杂度:

    • 构造函数:O(1)O(1)O(1)
    • generate():O(1)O(1)O(1),哈希表的插入操作即为 O(1)O(1)O(1) 的时间复杂度。
    • renew():O(1)O(1)O(1),哈希表的查找、删除操作均为 O(1)O(1)O(1) 的时间复杂度。
    • countUnexpiredTokens():O(n)O(n)O(n),其中 nnn 为哈希表中的验证码元素个数,或者说就是函数 generate() 的调用次数。
  • 空间复杂度:O(n)O(n)O(n)。其中 nnn 为函数 generate() 的调用次数,主要为哈希表的开销。

参考结果

Accepted
90/90 cases passed (76 ms)
Your runtime beats 65.89 % of cpp submissions
Your memory usage beats 89.25 % of cpp submissions (29.3 MB)

若每次调用 generate()renew() 时都打算清理 过期的 验证码,那么由于函数 clearExpiredTokens() 的时间复杂度为 O(n)O(n)O(n) ,函数 generate()renew() 的时间复杂度也会继而变为 O(n)O(n)O(n)

参考结果如下:

Accepted
90/90 cases passed (92 ms)
Your runtime beats 34.58 % of cpp submissions
Your memory usage beats 93.46 % of cpp submissions (29.3 MB) 

相关文章:

【LeetCode每日一题】【2023/2/9】1797. 设计一个验证系统

文章目录1797. 设计一个验证系统方法1&#xff1a;哈希表代码总体1797. 设计一个验证系统 LeetCode: 1797. 设计一个验证系统 中等\color{#FFB800}{中等}中等 你需要设计一个包含验证码的验证系统。每一次验证中&#xff0c;用户会收到一个新的验证码&#xff0c;这个验证码在…...

计算机图形学:改进的中点BH算法

作者&#xff1a;非妃是公主 专栏&#xff1a;《计算机图形学》 博客地址&#xff1a;https://blog.csdn.net/myf_666 个性签&#xff1a;顺境不惰&#xff0c;逆境不馁&#xff0c;以心制境&#xff0c;万事可成。——曾国藩 文章目录专栏推荐专栏系列文章序一、改进缘由二、…...

【SQL开发实战技巧】系列(六):从执行计划看NOT IN、NOT EXISTS 和 LEFT JOIN效率,记住内外关联条件不要乱放

系列文章目录 【SQL开发实战技巧】系列&#xff08;一&#xff09;:关于SQL不得不说的那些事 【SQL开发实战技巧】系列&#xff08;二&#xff09;&#xff1a;简单单表查询 【SQL开发实战技巧】系列&#xff08;三&#xff09;&#xff1a;SQL排序的那些事 【SQL开发实战技巧…...

十分钟利用环信WebIM-vue3-Demo,打包上线一个即时通讯项目【含音视频通话】

这篇文章无废话&#xff0c;只教你如果接到即时通讯功能需求&#xff0c;十分钟利用环信WebIM-vue3-Demo&#xff0c;打包上线一个即时通讯项目【包含音视频通话功能】。 写这篇文章是因为&#xff0c;结合自身情况&#xff0c;以及所遇到的有同样情况的开发者在接到即时通讯&a…...

pandas——DataFrame基本操作(二)【建议收藏】

pandas——DataFrame基本操作&#xff08;二&#xff09; 文章目录pandas——DataFrame基本操作&#xff08;二&#xff09;一、实验目的二、实验原理三、实验环境四、实验内容五、实验步骤1.修改数据2.缺失值3.合并1.concat合并2.使用append方法合并3.使用merge进行合并4.使用…...

PostgreSQL查询引擎——General Expressions Grammar之restricted expression

General expressions语法规则定义在src/backend/parser/gram.y文件中&#xff0c;其是表达式语法的核心。有两种表达式类型&#xff1a;a_expr是不受限制的类型&#xff0c;b_expr是必须在某些地方使用的子集&#xff0c;以避免移位/减少冲突。例如&#xff0c;我们不能将BETWE…...

从某种程度上来看,产业互联网是一次对于互联网的弥补和修正

如果对当下我们正在经历的这样一个时代进行一次定义的话&#xff0c;我更加愿意将其划归到产业互联网的范畴里。可能有人会说&#xff0c;这与产业互联网并无联系&#xff0c;因为从本质上来看&#xff0c;当下我们所经历的这样一个时代&#xff0c;其实是与互联网并没有太多联…...

【C#Unity题】1.委托和事件在使用上的区别是什么?2.C#中 == 和 Equals 的区别是什么?

1.委托和事件在使用上的区别是什么&#xff1f; 委托和事件是C#中的重要概念&#xff0c;通俗来讲&#xff0c;委托是一个可以指向特定方法的指针&#xff0c;可以将委托分配给不同的脚本&#xff0c;使它们能够完成不同的任务。而事件则是一种使用委托实现的通知机制&#xff…...

FFmpeg5.0源码阅读——内存池AVBufferPool

摘要&#xff1a;FFmpeg中大多数数据存储比如AVFrame,AVPacket都是通过AVBufferRef管理的&#xff0c;而承载数据的结构为AVBuffer。本文主要通过FFmpeg源码来分析下FFmpeg中AVBuffer相关的实现。 关键字&#xff1a;AVBuffer、AVBufferPool、AVBufferPool 1. AVBufferRef 1.…...

Python学习------起步7(字符串的连接、删除、修改、查询与统计、类型判断及字符串字母大小写转换)

目录 前言&#xff1a; 1.字符串的连接 join() 函数 2.字符串的删除&取代 replace()函数 3.字符串的修改&切割 &#xff08;1&#xff09;strip() 函数 &#xff08;2&#xff09;lstrip()函数 和 rstrip()函数 &#xff08;3&#xff09;split()函数-->…...

雪花算法snowflake

snowflake中文的意思是 雪花&#xff0c;雪片&#xff0c;所以翻译成雪花算法。它最早是twitter内部使用的分布式环境下的唯一ID生成算法。在2014年开源。雪花算法产生的背景当然是twitter高并发环境下对唯一ID生成的需求&#xff0c;得益于twitter内部高超的技术&#xff0c;雪…...

Part 4 描述性统计分析(占比 10%)——上

文章目录【后续会持续更新CDA Level I&II备考相关内容&#xff0c;敬请期待】【考试大纲】【考试内容】【备考资料】1、统计基本概念1.1、统计学的含义及应用1.1.1、统计学的含义1.2.1、统计学的应用1.2、统计学的基本概念1.2.1、数据及数据的分类1.2.2、总体和样本1.2.3、…...

Linux系统安全:安全技术和防火墙

目录 一、安全技术 1、安全技术 2、防火墙分类 二、防火墙 1、iptables五表五链 2、黑白名单 3、iptables基本语法 4、iptables选项 5、控制类型 6、隐藏扩展模块 7、显示扩展模块 8、iptables规则保存 9、自定义链使用 一、安全技术 1、安全技术 ①入侵检测系统…...

【干货】Python:turtle库的用法

【干货】Python&#xff1a;turtle库的用法1. turtle库概述2. turtle库与基本绘图2.1 导入库的三种方式2.1.12.1.22.1.32.2 窗体函数2.2 画笔状态函数2.2.1 seed(s)2.2.2 random()2.2.3 randint(a, b)2.2.4 getrandbits(k)2.2.5 randrange(start, stop[ , step])2.2.6 uniform(…...

信息安全与网络安全有什么区别?

生活中我们经常会听到要保障自己的或者企业的信息安全。那到底什么是信息安全呢&#xff1f;信息安全包含哪些内容&#xff1f;与网络安全又有什么区别呢&#xff1f;今天我们就一起来详细了解一下。什么叫做信息安全&#xff1f;信息安全定义如下&#xff1a;为数据处理系统建…...

花了5年时间,用过市面上95%的工具,终于找到这款万能报表工具

经常有粉丝问我有“哪个报表工具好用易上手&#xff1f;”或者是“有哪些适合绝大多数普通职场人的万能报表工具&#xff1f;” 从这里我大概总结出了大家选择报表工具最期望满足的3点&#xff1a; &#xff08;1&#xff09;简单易上手&#xff1a;也就是所谓的学习门槛要低…...

ESP32S3系列--SPI主机驱动详解(一)

一、目的SPI是一种串行同步接口&#xff0c;可用于与外围设备进行通信。ESP32S3自带4个SPI控制器外设&#xff0c;其中SPI0/SPI1内部专用,共用一组信号线,通过一个仲裁器访问外部Flash和PSRAM&#xff1b;SPI2/3各自使用一组信号线&#xff1b;开发者可以使用SPI2/3控制外部SPI…...

2023开工开学火热!远行的人们,把淘特箱包送上顶流

春暖花开&#xff0c;被疫情偷走的三年在今年开学季找补回来了。多个数据反馈&#xff0c;居民消费意愿大幅提升。在淘特上&#xff0c;开工开学节点就很是明显&#xff1a;1月30日以来&#xff0c;淘特箱包品类甚至远超2022年双11&#xff0c;成为开年“第一爆品”。与此同时&…...

Intel x86_64 PMU简介

文章目录前言一、性能监控概述二、CPUID information三、架构性能监控3.1 架构性能监控 Version 13.1.1 架构性能监控 Version 1 Facilities3.1.2 预定义的体系结构性能事件3.1.3 cmask demo测试参考资料前言 Intel 64 和 IA-32 架构提供了 PMU&#xff08;Performance Monito…...

Vue (2)

文章目录1. 模板语法1.1 插值语法1.2 指令语法2. 数据绑定3. 穿插 el 和 data 的两种写法4. MVVM 模型1. 模板语法 root 容器中的代码称为 vue 模板 1.1 插值语法 1.2 指令语法 图一 &#xff1a; 简写 &#xff1a; v-bind: 是可以简写成 &#xff1a; 的 总结 &#xff1a; …...

ESP8266 + STC15基于AT指令通过TCP通讯协议获取时间

ESP8266 + STC15基于AT指令通过TCP通讯协议获取时间 如果纯粹拿32位的ESP8266模块给8位的单片机仅供授时工具使用,有点大材小用了。这里不讨论这个拿esp8266来单独开发使用。本案例只是通过学习esp8266 AT指令功能来验证方案的可行性。 🔖STC15 单片机采用的是:STC15F2K60S…...

谈谈Spring中Bean的生命周期?(让你瞬间通透~)

目录 1.Bean的生命周期 1.1、概括 1.2、图解 2、代码示例 2.1、初始化代码 2.2、初始化的前置方法和后置方法&#xff08;重写&#xff09; 2.3、Spring启动类 2.4、执行结果 2.5、经典面试问题 3.总结 1.Bean的生命周期 1.1、概括 Spring中Bean的生命周期就是Bean在…...

如何将VirtualBox虚拟机转换到VMware中

转换前的准备 首先需要你找到你的virtualbox以及VM安装到哪个文件夹里了&#xff0c;需要将这两个文件夹添加进环境变量Path中。 如果你记不清了&#xff0c;可以用everything全局搜索一下“VBoxManage.exe’以及“vmware-vdiskmanager.exe”&#xff0c;看一眼这个程序放到哪…...

洞庭龙梦(开发技巧和结构理论集)

1、经验来源&#xff0c;单一获取方式。进行形态等级展示。唯一游戏系统经验来源。无主线和支线剧情。2、玩家使用流通货币&#xff08;充值货币&#xff09;&#xff0c;到玩家空间商城充值游戏&#xff0c;两人以上玩家进行游戏&#xff0c;掉落道具。交易系统游戏玩法&#…...

【23种设计模式】创建型模式详细介绍

前言 本文为 【23种设计模式】创建型模式详细介绍 相关内容介绍&#xff0c;下边具体将对单例模式&#xff0c;工厂方法模式&#xff0c;抽象工厂模式&#xff0c;建造者模式&#xff0c;原型模式&#xff0c;具体包括它们的特点与实现等进行详尽介绍~ &#x1f4cc;博主主页&…...

@Bean的处理流程,源码分析@Bean背后发生的事

文章目录写在前面关键类ConfigurationClassPostProcessor1、ConfigurationClassPostProcessor的注册2、ConfigurationClassPostProcessor的处理过程&#xff08;1&#xff09;parse方法中&#xff0c;Bean方法的处理&#xff08;2&#xff09;注册解析Bean标注的方法写在前面 …...

企业网站建设的方案ppt/沈阳网络营销推广的公司

添加一个maven管理的工程后&#xff0c;需要配置jdk&#xff0c;但是右键工程的属性后&#xff0c;没有出现java path build。 网上查了一下&#xff0c;总结方法如下&#xff1a;找到工程下的.project文件&#xff0c;打开&#xff0c;添加红色框图中的内容。 最后&#xff0c…...

wordpress $wpdb 查询/做一个微信小程序需要多少钱

文章目录一. 知识点1.1 网页请求1.2 django使用的模式 MTV1.3 django 模板语法1.4 django的一些技巧二. 数据表的设计(可以想成做Excel)2.1 表实际配置a 创建表b. 创建表的视图2.2 注意三. 注册-激活-登录-退出-登录3.1 注册流程3.2 用到的重要方法3.3 创建管理视图 admin.py3.…...

天猫店铺转让平台/网站关键词优化多少钱

简介 本文主要探索在转码前探测流格式和流信息完成后&#xff0c;怎样将处理过的数据进行转码&#xff0c;而不至于丢失。 这个问题实际上就是要探索ffmpeg中的读取数据和缓冲数据系统是如何运作的。了解了这些可以帮助 我们在转码过程中方便的处理数据。 各函数探索 从内…...

销售网站开发与设计现状/前端seo是什么意思

全局变量什么是全局变量&#xff1f;全局变量就好比一个容器或者一个公用的东西一样&#xff0c;就类似外面公共场所的凳子一样&#xff0c;大家都可以使用这个凳子。和他相反的局部变量是啥子东东呢&#xff1f;局部变量就是局部的东西&#xff0c;如果全局变量是桌子&#xf…...

博望网站建设/佛山网页搜索排名提升

目录 创建项目项目结构编码实现通过上面章节&#xff0c;我们已经了解如何配置一个ArcGIS Runtime for Android开发环境&#xff0c;下面我们将介绍如何使用Eclipse创建一个ArcGIS移动项目Hello World Map&#xff0c;并且分析项目的相关结构。 1、 创建项目 打开我们已经配置…...

详述电子商务网站的建设/怎么在百度上做广告推广

【例9-23】最长公共子序列【问题描述】w一个给定序列的子序列是在该序列中删去若干元素后得到的序列。确切地说&#xff0c;若给定序列X1,x2,…,xm>&#xff0c;则另一序列Z&#xff1d;1&#xff0c;z2&#xff0c;…&#xff0c;zk>是X的子序列是指存在一个严格递增的下…...