0
点赞
收藏
分享

微信扫一扫

[leetcode周赛]第300场——6109. 知道秘密的人数-中等

言午栩 2022-07-12 阅读 71

​​6109. 知道秘密的人数​​

在第 1 天,有一个人发现了一个秘密。

给你一个整数 delay ,表示每个人会在发现秘密后的 delay 天之后,每天 给一个新的人 分享 秘密。同时给你一个整数 forget ,表示每个人在发现秘密 forget 天之后会 忘记 这个秘密。一个人 不能 在忘记秘密那一天及之后的日子里分享秘密。

给你一个整数 n ,请你返回在第 n 天结束时,知道秘密的人数。由于答案可能会很大,请你将结果对 109 + 7 取余 后返回。


示例 1:

输入:n = 6, delay = 2, forget = 4

输出:5

解释:

第 1 天:假设第一个人叫 A 。(一个人知道秘密)

第 2 天:A 是唯一一个知道秘密的人。(一个人知道秘密)

第 3 天:A 把秘密分享给 B 。(两个人知道秘密)

第 4 天:A 把秘密分享给一个新的人 C 。(三个人知道秘密)

第 5 天:A 忘记了秘密,B 把秘密分享给一个新的人 D 。(三个人知道秘密)

第 6 天:B 把秘密分享给 E,C 把秘密分享给 F 。(五个人知道秘密)

示例 2:

输入:n = 4, delay = 1, forget = 3

输出:6

解释:

第 1 天:第一个知道秘密的人为 A 。(一个人知道秘密)

第 2 天:A 把秘密分享给 B 。(两个人知道秘密)

第 3 天:A 和 B 把秘密分享给 2 个新的人 C 和 D 。(四个人知道秘密)

第 4 天:A 忘记了秘密,B、C、D 分别分享给 3 个新的人。(六个人知道秘密)

 

提示:

2 <= n <= 1000

1 <= delay < forget <= n

来源:力扣(LeetCode)

链接:https://leetcode.cn/problems/number-of-people-aware-of-a-secret

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。


题解

方法一:使用hash表的实现

思路:

使用hash表存放第i天知道的人数,然后当到达第i天的时候,减去当天遗忘的人数,再加上当天新增的人数,最后再用hash表存放当天新增的人数,当到达第n+1天的时候退出循环。

代码如下:

class Solution {
public:
int peopleAwareOfSecret(int n, int delay, int forget)
{
long mod = 1e9 + 7;
std::unordered_map<long, long> m; // key==>第几天,value==>这天有几个人知道
m[1] = 1;
long i = 1; // 第几天
long total = 1;
while (i <= n)
{
if (i > forget)// 当天遗忘的人数
{
if (m.find(i - forget) != m.end())
{
long v = m[i - forget];
if (total < v)
{
total += mod;
}
total -= v;
m.erase(i - forget);
}
}

if (i > delay)
{
long today = 0;// 当天新增的人数
for (long k = i; k >= i - forget; --k)
{
if (i - k < delay)
{
continue;
}
if (m.find(k) == m.end())
{
continue;
}
today += m[k];
}
if (today > 0)
{
today %= mod;
total = (total + today) % mod;
m[i] = today;
}
}
i++;
}
return total % mod;
}
};

方法二:动态规划解法

思路:

  1. 定义dp[i]为第i天新增的知道秘密的人数
  2. 初始化:dp[0] = 0,dp[1] = 1
  3. 状态转移方程:dp[i] = accumulate(dp+(i-forget+1),dp+(i-delay)) - dp[i-forget],也就是第i天新增的人数等于在[i-forget+1,i-delay]区间之和,再减dp[i-forget](表示这一天要遗忘这么多人)
  4. 返回值:使用一个整形累加每天新增人数以及减去每天遗忘人数

代码从略,有兴趣可以看其他的人解法~~

举报

相关推荐

0 条评论