设计一个验证系统
难度:中等
你需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个新的验证码,这个验证码在 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 ,设置 timeToLive = 5 秒。
AuthenticationManager authenticationManager = new AuthenticationManager(5);
// 时刻 1 时,没有验证码的 tokenId 为 "aaa" ,没有验证码被更新。
authenticationManager.renew("aaa", 1);
// 时刻 2 时,生成一个 tokenId 为 "aaa" 的新验证码。
authenticationManager.generate("aaa", 2);
// 时刻 6 时,只有 tokenId 为 "aaa" 的验证码未过期,所以返回 1 。
authenticationManager.countUnexpiredTokens(6);
// 时刻 7 时,生成一个 tokenId 为 "bbb" 的新验证码。
authenticationManager.generate("bbb", 7);
// tokenId 为 "aaa" 的验证码在时刻 7 过期,且 8 >= 7 ,所以时刻 8 的renew 操作被忽略,没有验证码被更新。
authenticationManager.renew("aaa", 8);
// tokenId 为 "bbb" 的验证码在时刻 10 没有过期,所以 renew 操作会执行,该 token 将在时刻 15 过期。
authenticationManager.renew("bbb", 10);
// tokenId 为 "bbb" 的验证码在时刻 15 过期,tokenId 为 "aaa" 的验证码在时刻 7 过期,所有验证码均已过期,所以返回 0 。
authenticationManager.countUnexpiredTokens(15);
哈希表
思路:
按照题意,用一个哈希表
history
\textit{history}
history 保存验证码和过期时间。调用
generate
\textit{generate}
generate 时,将验证码-过期时间对直接插入
history
\textit{history}
history。调用
renew
\textit{renew}
renew 时,如果验证码存在并且未过期,则更新过期时间。调用
countUnexpiredTokens
\textit{countUnexpiredTokens}
countUnexpiredTokens 时,遍历整个
history
\textit{history}
history,统计未过期的验证码的数量。
复杂度分析:
- 时间复杂度: 构造函数: O ( 1 ) O(1) O(1), generate \textit{generate} generate: O ( 1 ) O(1) O(1), renew \textit{renew} renew: O ( 1 ) O(1) O(1), countUnexpiredTokens \textit{countUnexpiredTokens} countUnexpiredTokens: O ( n ) O(n) O(n),其中 n n n 为 generate \textit{generate} generate 的调用次数。
- 空间复杂度: O ( n ) O(n) O(n),其中 n n n 为 generate \textit{generate} generate 的调用次数, history \textit{history} history 中有 n n n 个元素。
class AuthenticationManager:
def __init__(self, timeToLive: int):
self.timeToLive = timeToLive
self.history = dict()
def generate(self, tokenId: str, currentTime: int) -> None:
self.history[tokenId] = currentTime + self.timeToLive
def renew(self, tokenId: str, currentTime: int) -> None:
if tokenId in self.history and self.history[tokenId] > currentTime:
self.history[tokenId] = currentTime + self.timeToLive
def countUnexpiredTokens(self, currentTime: int) -> int:
res = 0
for i in self.history.values():
if i > currentTime:
res += 1
return res
# Your AuthenticationManager object will be instantiated and called as such:
# obj = AuthenticationManager(timeToLive)
# obj.generate(tokenId,currentTime)
# obj.renew(tokenId,currentTime)
# param_3 = obj.countUnexpiredTokens(currentTime)
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/design-authentication-manager