[差分数组]2327. 知道秘密的人数
2327. 知道秘密的人数
这个解决方案使用差分数组(Difference Array)高效地处理了区间修改问题,计算第 n
天结束时知道秘密的人数。以下是代码的详细解释:
核心思路
- 1.差分数组
diff
:- •用于记录每天知道秘密人数的变化量(增量或减量)。
- •初始化:
diff[1] = 1
表示第 1 天新增 1 人(初始知道秘密的人),diff[2] = -1
是为了在差分数组中标记区间结束(确保前缀和计算正确)。
- 2.变量说明:
- •
know
:记录当前第i
天结束时知道秘密的总人数(包括当天新增和之前未忘记的人)。 - •
ans
:累计最后forget
天内知道秘密的人数(即第n
天结束时未忘记的人)。
- •
- 3.处理逻辑:
- •
遍历每一天
i
(从 1 到n
):- •
更新
know
:know = (know + diff[i]) % MOD
,加上当天的变化量(新增或减少)。 - •
累加答案:如果
i >= n - forget + 1
,说明当前know
中的人在第n
天结束时未忘记,累加到ans
。 - •
传播秘密:当前
know
中的人会在i + delay
天分享秘密,导致那天新增know
人,因此更新diff[i + delay] += know
。 - •
忘记秘密:当前
know
中的人会在i + forget
天忘记,因此更新diff[i + forget] -= know
。
- •
- •
使用
min(i + delay, n + 1)
和min(i + forget, n + 1)
确保不越界。
- •
关键点解析
- •
差分数组的作用:将区间修改(如多人同时分享或忘记)转换为两个端点的修改,时间复杂度从 O(n) 降为 O(1)。
- •
know
的含义:表示第i
天结束时知道秘密的总人数,包括当天新增和之前未忘记的人。 - •
传播与忘记的时机:
- •
分享:第
i
天的人会在i + delay
天分享,导致那天新增know
人。 - •
忘记:第
i
天的人会在i + forget
天忘记,导致那天减少know
人。
- •
- •
答案计算:最后
forget
天(i >= n - forget + 1
)的know
之和,因为这些人第n
天结束时未忘记。
示例说明
以 n = 6, delay = 2, forget = 4
为例:
- •
第 1 天:
know = 1
(初始人),传播到第 3 天(diff[3] += 1
),忘记在第 5 天(diff[5] -= 1
)。 - •
第 2 天:
know = 0
(无变化)。 - •
第 3 天:
know = 1
(第 3 天新增),传播到第 5 天(diff[5] += 1
),忘记在第 7 天(越界忽略)。 - •
第 4 天:
know = 1
(第 4 天新增),传播到第 6 天(diff[6] += 1
),忘记在第 8 天(越界忽略)。 - •
第 5 天:
know = 1
(第 5 天新增),传播到第 7 天(越界),忘记在第 9 天(越界)。 - •
第 6 天:
know = 2
(第 6 天新增),传播和忘记越界。 - •
最后
forget
天(第 3 到 6 天):ans = 1 + 1 + 1 + 2 = 5
。
复杂度
- •
时间复杂度:O(n),遍历每一天,每次更新差分数组的端点。
- •
空间复杂度:O(n),差分数组长度
n + 2
。
代码总结
class Solution:def peopleAwareOfSecret(self, n: int, delay: int, forget: int) -> int:MOD = 1000000007diff = [0] * (n + 2) # 差分数组,长度 n+2 防越界diff[1] = 1 # 第 1 天新增 1 人diff[2] = -1 # 差分结束标记ans = 0know = 0 # 当前知道秘密的总人数for i in range(1, n + 1): # 遍历每一天know = (know + diff[i]) % MOD # 更新当前知道人数if i >= n - forget + 1: # 最后 forget 天内的人未忘记ans = (ans + know) % MOD# 传播:当前 know 人会在 i+delay 天新增 know 人diff[min(i + delay, n + 1)] = (diff[min(i + delay, n + 1)] + know) % MOD# 忘记:当前 know 人会在 i+forget 天减少 know 人diff[min(i + forget, n + 1)] = (diff[min(i + forget, n + 1)] - know) % MODreturn ans % MOD
此方案高效利用差分数组处理动态区间修改,适用于大量区间操作的场景。