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

文章介绍了一个需要设计的验证系统,该系统使用验证码并在给定时间内过期。系统包含生成新验证码、更新验证码有效期以及计算未过期验证码数量的功能。提供的C++解决方案使用了两个HashMap来跟踪令牌的有效性,但存在超时问题。官方提供的解决方案则更为高效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、题目

你需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个新的验证码,这个验证码在 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 操作),过期事件 优先于 其他操作。

示例

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

来源:力扣(LeetCode)
链接:

二、C++解法

我的思路及代码

此代码在力扣超时,但是我觉得力扣评判的不标准
用两个哈希表,第一个存储token到期时间,第二个存储当前时间有几个未过期的token。
新建操作:更新token的到期时间,并且更新这个持续时间中的token数量。
更新操作:判断当前token是否到期,若还有效则更新token的到期时间,并且从原来的到期时间开始直到新的到期时间结束的时间内继续增加token数量。

class AuthenticationManager {
public:
    int timeToLive;
    unordered_map<string,int> tokenAndTimePast;
    unordered_map<int,int> countTokens;
    AuthenticationManager(int timeToLive) {
        this->timeToLive = timeToLive;
    }
    
    void generate(string tokenId, int currentTime) {
        tokenAndTimePast[tokenId] = currentTime+timeToLive;
        for(int i=currentTime;i<currentTime+timeToLive;i++){
            countTokens[i]++;
        }
    }
    
    void renew(string tokenId, int currentTime) {
    	//当tokenId不存在的时候,他对应的值为0,所以可以用这个条件来判断
        if(tokenAndTimePast[tokenId]>currentTime){
            for(int i=tokenAndTimePast[tokenId];i<currentTime+timeToLive;i++){
                countTokens[i]++;
            }
            tokenAndTimePast[tokenId] = currentTime+timeToLive;
        }
    }
    
    int countUnexpiredTokens(int currentTime) {
        return countTokens[currentTime];
    }
};

/**
 * Your AuthenticationManager object will be instantiated and called as such:
 * AuthenticationManager* obj = new AuthenticationManager(timeToLive);
 * obj->generate(tokenId,currentTime);
 * obj->renew(tokenId,currentTime);
 * int param_3 = obj->countUnexpiredTokens(currentTime);
 */
  • 时间复杂度:
  • 构造函数:O(1)
  • generate:O(n),其中 n 为 currentTime 的秒数
  • renew:O(n),其中 n 为 currentTime 的秒数
  • 官方写的:countUnexpiredTokens:O(n),其中 n 为 generate 的调用次数。
  • 空间复杂度:O(n),两个 map 中 n 都为 generate 的调用次数。

官方参考代码

class AuthenticationManager {
private:
    int timeToLive;
    unordered_map<string, int> mp;
public:
    AuthenticationManager(int timeToLive) {
        this->timeToLive = timeToLive;
    }

    void generate(string tokenId, int currentTime) {
        mp[tokenId] = currentTime + timeToLive;
    }

    void renew(string tokenId, int currentTime) {
        if (mp.count(tokenId) && mp[tokenId] > currentTime) {
            mp[tokenId] = currentTime + timeToLive;
        }
    }

    int countUnexpiredTokens(int currentTime) {
        int res = 0;
        for (auto &[_, time] : mp) {
            if (time > currentTime) {
                res++;
            }
        }
        return res;
    }
};

  • 时间复杂度:
  • 构造函数:O(1)
  • generate:O(1)
  • renew:O(1)
  • 官方写的:countUnexpiredTokens:O(n),其中 n 为 generate 的调用次数。我认为的:countUnexpiredTokens里面带有 for 循环,循环次数和 mp 的个数相关,而 mp 的个数和 tokenId 的数量相关,所以我认为是 countUnexpiredTokens :O(nt),其中 n 为 generate 的调用次数,t 为 tokenId 的数量
  • 空间复杂度:O(n),其中 n 为 generate 的调用次数,map 中有 n 个元素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天地神仙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值