当前位置: 首页 > 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; …...

OpenLayers 可视化之热力图

注&#xff1a;当前使用的是 ol 5.3.0 版本&#xff0c;天地图使用的key请到天地图官网申请&#xff0c;并替换为自己的key 热力图&#xff08;Heatmap&#xff09;又叫热点图&#xff0c;是一种通过特殊高亮显示事物密度分布、变化趋势的数据可视化技术。采用颜色的深浅来显示…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

代码随想录刷题day30

1、零钱兑换II 给你一个整数数组 coins 表示不同面额的硬币&#xff0c;另给一个整数 amount 表示总金额。 请你计算并返回可以凑成总金额的硬币组合数。如果任何硬币组合都无法凑出总金额&#xff0c;返回 0 。 假设每一种面额的硬币有无限个。 题目数据保证结果符合 32 位带…...

小木的算法日记-多叉树的递归/层序遍历

&#x1f332; 从二叉树到森林&#xff1a;一文彻底搞懂多叉树遍历的艺术 &#x1f680; 引言 你好&#xff0c;未来的算法大神&#xff01; 在数据结构的世界里&#xff0c;“树”无疑是最核心、最迷人的概念之一。我们中的大多数人都是从 二叉树 开始入门的&#xff0c;它…...

VASP软件在第一性原理计算中的应用-测试GO

VASP软件在第一性原理计算中的应用 VASP是由维也纳大学Hafner小组开发的一款功能强大的第一性原理计算软件&#xff0c;广泛应用于材料科学、凝聚态物理、化学和纳米技术等领域。 VASP的核心功能与应用 1. 电子结构计算 VASP最突出的功能是进行高精度的电子结构计算&#xff…...

迁移科技3D视觉系统:重塑纸箱拆垛场景的智能革命

一、传统拆垛场景的困局与破局之道 在汽车零部件仓库中&#xff0c;每天有超过2万只异形纸箱需要拆垛分拣。传统人工拆垛面临三大挑战&#xff1a; 效率瓶颈&#xff1a;工人每小时仅能处理200-300件&#xff0c;且存在间歇性疲劳安全隐患&#xff1a;20kg以上重箱搬运导致年…...

Docker 镜像上传到 AWS ECR:从构建到推送的全流程

一、在 EC2 实例中安装 Docker&#xff08;适用于 Amazon Linux 2&#xff09; 步骤 1&#xff1a;连接到 EC2 实例 ssh -i your-key.pem ec2-useryour-ec2-public-ip步骤 2&#xff1a;安装 Docker sudo yum update -y sudo amazon-linux-extras enable docker sudo yum in…...

【计算机网络】NAT、代理服务器、内网穿透、内网打洞、局域网中交换机

&#x1f525;个人主页&#x1f525;&#xff1a;孤寂大仙V &#x1f308;收录专栏&#x1f308;&#xff1a;计算机网络 &#x1f339;往期回顾&#x1f339;&#xff1a;【计算机网络】数据链路层——ARP协议 &#x1f516;流水不争&#xff0c;争的是滔滔不息 一、网络地址转…...