【LeetCode动态规划#17】知道秘密的人,维护多个dp数组
知道秘密的人数
在第 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
思路
简单来说就是将当前的人分为三类:知道秘密的人、遗忘秘密的人、正在分享秘密的人
然后使用者三类人进行互推与计算。
知道秘密的人可能会与正在分享秘密的人有重合
例如:A在第一天知道了秘密,假设延迟天数delay为3,那么他在第3天可以分享秘密,如果第3天A把秘密分享给了B,那么现在知道秘密的人就有2个,但是正在分享秘密的人还是只有A一个,因为B还没到延迟天数
代码
在实现上,我们需要维护3个dp数组,具体如下:
class Solution {
public:
int peopleAwareOfSecret(int n, int delay, int forget) {
long long mod = 1000000007;
vector<int> dpKnow(n + 1, 0);//第i天知道秘密的人(还不能分享,因为还没到delay天,可以分享后会转变为dpShare)
vector<int> dpForget(n + 1, 0);//第i天忘了秘密的人
vector<int> dpShare(n + 1, 0);//第i天可以分享秘密的人(注意,这部分人与知道秘密的人是有重合的)
//初始化分为两部分:初始化第一天时三个数组的值、根据第一天的值计算出后面天数中可以确定的值
//第1天的时候,知道秘密的人1个
//第1天的时候,将要忘记秘密的人0个
//第1天的时候,可以分享秘密的人0个
dpKnow[1] = 1;//后两个就不用填了
//然后我们依据dpKnow在第一天的情况,计算出dpForget和dpShare在后续天数中的值
//那么这个人在forget天之后会忘掉秘密,因此我们可以求出1 + forget天时dpForget的情况
if(1 + forget <= n){//假设第一个人是A,那么A会在1 + forget天时忘掉秘密,此时忘掉秘密的人只有他一个
dpForget[1 + forget] = 1;
}
//第一个知道秘密的人肯定是要到1 + delay天之后才可以分享,因此dpShare在1 + deelay天时的值为1
if(1 + delay <= n){
dpShare[1 + delay] = 1;
}
//第二天之后!
for(int i = 2; i <= n; ++i){
//我们也还是先看第i天有几个人知道秘密,根据dpKnow的含义可得计算方法如下:
//dpKnow[i] = dpKnow[i - 1] - dpForget[i] + dpShare[i]
//即:第i天知道秘密的人 = 第i - 1天知道秘密的人 - 第i天忘掉秘密的人 + 第i天被分享了秘密的人
dpKnow[i] = (mod + dpKnow[i - 1] - dpForget[i] + dpShare[i]) % mod;
//然后计算之后会忘记的人,可以参考初始化时的计算方式:第一天有1个人,那么这个人在1 + forget天会忘掉
//同理,第i天新增了多少知道秘密的人,那么这些人在i + forget天后就会忘掉秘密
if(i + forget <= n){//i + forget天前知道秘密的早忘了,i + forget之后知道的肯定不会忘
dpForget[i + forget] = dpShare[i];
}
//最后计算第i天新增了多少可以分享秘密的人
//来到第i天时,可以分享秘密的人是:第i天熬过了delay天的新增加的知道秘密的人和之前可以分享秘密的人(并且这些人到第i天还没忘)
//举个例子:
//第7天,当前有一堆可以分享秘密的人.他们中有一些可能是第6天满足delay期限后变成可以分享的,也有一些可能已经分享了几天并且快忘了的
//然后第7天还会产生一堆被分享后知道秘密的新人,这些新人现在还不能分享秘密
//那么等到了7 + delay天,此时在第7天产生的新人就都可以分享秘密了,并且还留有一部分第7天已经在分享秘密并且7 + delay天还没忘的人
//这两部分人共同构成了7 + delay天可以分享秘密的人的人员构成,也就是dpShare[7 + delay]
if(i + delay <= n){
dpShare[i + delay] = (mod + dpShare[i + delay - 1] - dpForget[i + delay] + dpShare[i]) % mod;
//dpShare[i]是在第i天新增的人,这些人在i + delay天时可以分享秘密
//dpShare[i + delay - 1] - dpForget[i + delay]是之前能够分享秘密的人,但这些人到了i + delay天要忘掉一批人(即减掉i + delay当天的遗忘人数dpForget[i + delay])
}
}
return dpKnow[n];
}
};
【LeetCode动态规划#17】知道秘密的人,维护多个dp数组的更多相关文章
- caioj 1080 动态规划入门(非常规DP4:乘电梯)(dp数组更新其他量)
我一开始是这么想的 注意这道题数组下标是从大到小推,不是一般的从小到大推 f[i]表示从最高层h到第i层所花的最短时间,答案为f[1] 那么显然 f[i] = f[j] + wait(j) + (j ...
- [LeetCode] 动态规划入门题目
最近接触了动态规划这个厉害的方法,还在慢慢地试着去了解这种思想,因此就在LeetCode上面找了几道比较简单的题目练了练手. 首先,动态规划是什么呢?很多人认为把它称作一种"算法" ...
- LeetCode动态规划题总结【持续更新】
以下题号均为LeetCode题号,便于查看原题. 10. Regular Expression Matching 题意:实现字符串的正则匹配,包含'.' 和 '*'.'.' 匹配任意一个字符,&quo ...
- leetcode动态规划题目总结
Hello everyone, I am a Chinese noob programmer. I have practiced questions on leetcode.com for 2 yea ...
- Leetcode 动态规划 - 简单
1. 最大子序和 (53) 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5,4], 输 ...
- 快速上手leetcode动态规划题
快速上手leetcode动态规划题 我现在是初学的状态,在此来记录我的刷题过程,便于以后复习巩固. 我leetcode从动态规划开始刷,语言用的java. 一.了解动态规划 我上网查了一下动态规划,了 ...
- House Robber III leetcode 动态规划
https://leetcode.com/submissions/detail/56095603/ 这是一道不错的DP题!自己想了好久没有清晰的思路,参看大神博客!http://siukwan.sin ...
- [leetcode] 动态规划(Ⅰ)
这次按通过率从高到低刷题. 本文完成的题目:{338, 1025, 303, 121, 53, 392, 70, 746, 198} ,带有「面试」Tag 的题目:Interview - {1617, ...
- 【LeetCode动态规划#04】不同的二叉搜索树(找规律,有点像智力题)
不同的二叉搜索树 力扣题目链接(opens new window) 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 思路 题意分析 先找一下关系 当n = 1时,如果 ...
- 【LeetCode动态规划#08】完全背包问题实战与分析(零钱兑换II)
零钱兑换II 力扣题目链接(opens new window) 给定不同面额的硬币和一个总金额.写出函数来计算可以凑成总金额的硬币组合数.假设每一种面额的硬币有无限个. 示例 1: 输入: amoun ...
随机推荐
- Windows 修改时间提示: 某些设置已隐藏或由你的组织管理 的解决方案
最近公司的一台生产服务器时间不对. 因为机器有域控的需求, 所以加入了域, 想改时间时有这样的提示信息: 某些设置已隐藏或由你的组织管理 百度了很久发现没有解决方法.. 但是突然发现可以使用 运行-& ...
- [转帖]awk命令 去掉重复行
https://developer.aliyun.com/article/885946?spm=a2c6h.24874632.expert-profile.263.7c46cfe9h5DxWK lin ...
- K8S 使用loki 监控 应用日志的搭建办法
1. 背景 这几天一直在用k8s部署分SU的测试环境,开发反馈看日志比较麻烦. 昨天晚上在家里本来想搭建ELK 发现比较重, 又说有一个比较轻量级的 loki 可以实现使用grafana进行监控和查看 ...
- Flutter开发桌面应用的一些探索
引言 在移动应用开发领域,Flutter已经赢得了广泛的认可和采用,成为了跨平台移动应用开发的瑞士军刀.然而,Flutter的魅力并不仅限于移动平台,它还可以用于开发桌面应用程序,为开发人员提供了一种 ...
- ARC150D - Removing Gacha (树上期望)
Link 题意: 给一棵 \(n\) 个节点的树,称一个点是好的,当且仅当它到根的路径上都是黑色(包括自己).每次在不好的节点中随机选一个把它涂成黑色(不管原来它是否是白的),直到所有点都是好的为止. ...
- vite引入图片
vite引入图片出现的问题 -不能够页面 <template> <div> <div> <img class="imgsize" sr=& ...
- 【K哥爬虫普法】大众点评VS百度地图,论“数据权属”对爬虫开发的罪与罚!
我国目前并未出台专门针对网络爬虫技术的法律规范,但在司法实践中,相关判决已屡见不鲜,K哥特设了"K哥爬虫普法"专栏,本栏目通过对真实案例的分析,旨在提高广大爬虫工程师的法律意识,知 ...
- x86 x64 arm64的区别
我们常说的高通 865,麒麟990 不是 CPU 是 SoC(System On Chip),SoC 除了 CPU 外,还有 GPU,还有可选的浮点数加速器,专用于深度模型的加速器,等等.除此以外,S ...
- Linux(Centos7)升级MySQL 5.7到8.0.31
一.下载MySQL安装包 下载地址:https://downloads.mysql.com/archives/community/ 二.备份 mkdir /home/mysqlback mysqldu ...
- NC223888 红色和紫色.md
题目链接 题目 题目描述 漫长的生命总是无聊的.这天,小红和紫准备玩一个染色游戏. 她们拿出了一个有 \(n*m\) 个格子的网格,每个格子只能被染成红色或紫色.每个人可以任意选择一个格子染成红色和紫 ...