1. 题目与解析
需要设计一个包含验证码的验证系统。每一次验证中,用户会收到一个新的验证码,这个验证码在 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 操作),过期事件 优先于 其他操作。
输入:
["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]
按照题意,用一个哈希表timeMap保存验证码和过期时间。调用 generate()时,将验证码-过期时间对直接插入timeMap。调用 renew() 时,如果验证码存在并且未过期,则更新过期时间。调用 countUnexpiredTokens() 时,遍历整个 timeMap,统计未过期的验证码的数量。
解体的过程中有两个需要注意的小细节
- 需要注意,调用
renew()时,需要进行是否过期的判断,如果过期了,就将其删除,不进行更新操作; - 另一个需要注意的点是,过期时间的判断过程是需要取等号的,距离来说,如果验证码在时间
t过期,那么当判断时间正好为t时,验证码就已经过期了。
2. 题解
class AuthenticationManager {
Map<String, Integer> timeMap;
int timeToLive;
public AuthenticationManager(int timeToLive) {
timeMap = new HashMap<>();
this.timeToLive = timeToLive;
}
public void generate(String tokenId, int currentTime) {
timeMap.put(tokenId, currentTime+timeToLive);
}
public void renew(String tokenId, int currentTime) {
if (!timeMap.containsKey(tokenId)) {
return;
}
if (timeMap.get(tokenId) <= currentTime) {
timeMap.remove(tokenId);
return;
}
timeMap.put(tokenId, currentTime+timeToLive);
}
public int countUnexpiredTokens(int currentTime) {
int ans = 0;
for (Map.Entry<String, Integer> e: timeMap.entrySet()) {
if (currentTime < e.getValue()) {
ans++;
}
}
return ans;
}
}