2327. Number of People Aware of a Secret
Problem Description
This problem simulates the spread and forgetting of a secret among people over time.
Initial Setup:
- On day 1, exactly one person discovers a secret.
Key Rules:
-
Sharing Rule: After a person discovers the secret, they wait for
delay
days before they can start sharing it. Once they can share, they share the secret with exactly one new person every day. -
Forgetting Rule: A person forgets the secret exactly
forget
days after discovering it. Once forgotten, they can no longer share the secret. -
Timing Constraint: A person cannot share the secret on the same day they forget it.
Example Timeline for One Person:
- Day 1: Person discovers the secret
- Days 2 to
delay
: Person knows the secret but cannot share yet - Days
delay + 1
toforget - 1
: Person actively shares the secret with one new person each day - Day
forget
: Person forgets the secret and stops sharing
Goal:
Given an integer n
, determine how many people know the secret at the end of day n
. Since the number can be very large, return the result modulo 10^9 + 7
.
Key Insight:
People who know the secret at day n
are those who:
- Discovered it recently enough that they haven't forgotten it yet (within the last
forget - 1
days) - This includes both people who can share and those still in their delay period
The challenge is tracking how many people discover the secret each day and managing when they start sharing and when they forget.
Intuition
To solve this problem, we need to track two key pieces of information for each day:
- How many people discover the secret on that day (
cnt[i]
) - How many people currently know the secret (
d[i]
using a difference array technique)
The main insight is that each person who discovers the secret follows a predictable pattern:
- They learn the secret on some day
i
- They start sharing from day
i + delay
- They continue sharing until day
i + forget - 1
- They forget on day
i + forget
This means if cnt[i]
people discover the secret on day i
, then:
- These
cnt[i]
people will each share with 1 new person per day from dayi + delay
to dayi + forget - 1
- These
cnt[i]
people will forget the secret on dayi + forget
We can use a difference array technique to efficiently track who knows the secret. When someone discovers the secret on day i
, we:
- Add them to the count of people who know:
d[i] += cnt[i]
- Schedule their forgetting:
d[i + forget] -= cnt[i]
For the sharing behavior, when cnt[i]
people discover the secret on day i
, they will share with others during their "active sharing window" which spans from day i + delay
to day i + forget - 1
. During each day in this window, cnt[i]
new people will discover the secret.
The final answer is the cumulative sum of the difference array up to day n
, which gives us the total number of people who know the secret on day n
. The difference array naturally handles both the addition of new people learning the secret and the subtraction of people forgetting it.
This approach efficiently simulates the entire process in O(n * (forget - delay))
time, avoiding the need to track each person individually.
Learn more about Queue and Dynamic Programming patterns.
Solution Approach
The solution uses two arrays to track the secret spreading dynamics:
Data Structures:
cnt[i]
: Number of people who discover the secret on dayi
d[i]
: Difference array to track people who know the secret
Implementation Steps:
-
Initialize Arrays:
m = (n << 1) + 10 # Buffer size (2*n + 10) to avoid index out of bounds d = [0] * m # Difference array cnt = [0] * m # Count of new discoveries per day cnt[1] = 1 # One person discovers on day 1
-
Main Simulation Loop (days 1 to n):
For each day
i
where people discover the secret (cnt[i] > 0
):a. Handle Knowledge and Forgetting:
d[i] += cnt[i] # People discover the secret on day i d[i + forget] -= cnt[i] # They forget on day i + forget
b. Handle Sharing:
nxt = i + delay # Start sharing from day i + delay while nxt < i + forget: # Share until day i + forget - 1 cnt[nxt] += cnt[i] # Each person shares with 1 new person nxt += 1
The loop ensures that
cnt[i]
people who discovered the secret on dayi
will each share with one new person every day during their active sharing period[i + delay, i + forget - 1]
. -
Calculate Final Answer:
return sum(d[: n + 1]) % mod
The cumulative sum of the difference array up to day
n
gives the total number of people who know the secret. We apply modulo10^9 + 7
to handle large numbers.
Example Walkthrough:
Let's say delay = 2
, forget = 4
, n = 6
:
- Day 1: Person 1 discovers (
cnt[1] = 1
)- Sets
d[1] += 1
(knows) andd[5] -= 1
(forgets on day 5) - Will share on days 3 and 4
- Sets
- Day 3: Person 1 shares with Person 2 (
cnt[3] = 1
) - Day 4: Person 1 shares with Person 3 (
cnt[4] = 1
) - Days 5-6: Person 2 and 3 continue sharing pattern
The difference array technique elegantly handles the addition and removal of people knowing the secret without explicitly tracking each person's state.
Ready to land your dream job?
Unlock your dream job with a 5-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's trace through a concrete example with n = 6
, delay = 2
, forget = 4
.
Initial Setup:
cnt[1] = 1
(one person discovers the secret on day 1)- All other arrays start at 0
Day 1 Processing (i = 1
, cnt[1] = 1
):
- Update difference array:
d[1] += 1
(person learns secret on day 1)d[5] -= 1
(person forgets on day 5)
- Schedule sharing for days 3-4 (from
1+2
to1+4-1
):cnt[3] += 1
(will share with 1 person on day 3)cnt[4] += 1
(will share with 1 person on day 4)
Day 2 Processing (i = 2
, cnt[2] = 0
):
- Nothing happens (no one discovers the secret on day 2)
Day 3 Processing (i = 3
, cnt[3] = 1
):
- One new person discovers the secret (shared by person from day 1)
- Update difference array:
d[3] += 1
(new person learns secret)d[7] -= 1
(will forget on day 7, outside our range)
- Schedule sharing for days 5-6 (from
3+2
to3+4-1
):cnt[5] += 1
cnt[6] += 1
Day 4 Processing (i = 4
, cnt[4] = 1
):
- Another person discovers the secret (shared by person from day 1)
- Update difference array:
d[4] += 1
d[8] -= 1
(outside our range)
- Schedule sharing for days 6-7:
cnt[6] += 1
(nowcnt[6] = 2
)cnt[7] += 1
Day 5 Processing (i = 5
, cnt[5] = 1
):
- Person from day 3 shares
- Update difference array:
d[5] += 1
d[9] -= 1
- Schedule sharing for days 7-8 (outside our range for this problem)
Day 6 Processing (i = 6
, cnt[6] = 2
):
- Two people discover the secret (shared by persons from days 3 and 4)
- Update difference array:
d[6] += 2
d[10] -= 2
Final Calculation:
Calculate cumulative sum of d
from days 1 to 6:
- Day 1:
d[1] = 1
, running sum = 1 - Day 2:
d[2] = 0
, running sum = 1 - Day 3:
d[3] = 1
, running sum = 2 - Day 4:
d[4] = 1
, running sum = 3 - Day 5:
d[5] = 1 - 1 = 0
, running sum = 3 - Day 6:
d[6] = 2
, running sum = 5
Answer: 5 people know the secret at the end of day 6
This matches our expectation: persons from days 3, 4, 5, and 6 (4 people total) still remember, plus 2 new discoveries on day 6 minus 1 person who forgot on day 5 = 5 people.
Solution Implementation
1class Solution:
2 def peopleAwareOfSecret(self, n: int, delay: int, forget: int) -> int:
3 # Buffer size to avoid index out of bounds
4 buffer_size = (n << 1) + 10 # n * 2 + 10
5
6 # Track people who currently know the secret at each day
7 people_knowing_secret = [0] * buffer_size
8
9 # Track new people learning the secret each day
10 new_people_each_day = [0] * buffer_size
11
12 # Day 1: one person initially knows the secret
13 new_people_each_day[1] = 1
14
15 # Simulate each day from 1 to n
16 for day in range(1, n + 1):
17 if new_people_each_day[day] > 0:
18 # Add new people who learn the secret today
19 people_knowing_secret[day] += new_people_each_day[day]
20
21 # These people will forget the secret after 'forget' days
22 people_knowing_secret[day + forget] -= new_people_each_day[day]
23
24 # Calculate when these people can start sharing (after delay)
25 # and continue sharing until they forget
26 start_sharing_day = day + delay
27 stop_sharing_day = day + forget
28
29 # Each person shares with one new person per day during their sharing period
30 for sharing_day in range(start_sharing_day, stop_sharing_day):
31 new_people_each_day[sharing_day] += new_people_each_day[day]
32
33 # Calculate total people who know the secret on day n
34 # Use modulo to prevent overflow as per problem requirements
35 MOD = 10**9 + 7
36 total_people_knowing = sum(people_knowing_secret[:n + 1])
37
38 return total_people_knowing % MOD
39
1class Solution {
2 private static final int MOD = (int) 1e9 + 7;
3
4 public int peopleAwareOfSecret(int n, int delay, int forget) {
5 // Array size with buffer to avoid index out of bounds
6 int arraySize = (n << 1) + 10; // n * 2 + 10
7
8 // Track the net change in people who know the secret on each day
9 long[] peopleKnowingSecret = new long[arraySize];
10
11 // Track new people who learn the secret on each day
12 long[] newPeoplePerDay = new long[arraySize];
13
14 // Day 1: One person initially knows the secret
15 newPeoplePerDay[1] = 1;
16
17 // Process each day from 1 to n
18 for (int currentDay = 1; currentDay <= n; ++currentDay) {
19 // If new people learned the secret on this day
20 if (newPeoplePerDay[currentDay] > 0) {
21 // Add new people to the count of people knowing the secret
22 peopleKnowingSecret[currentDay] = (peopleKnowingSecret[currentDay] +
23 newPeoplePerDay[currentDay]) % MOD;
24
25 // Schedule when these people will forget the secret
26 peopleKnowingSecret[currentDay + forget] =
27 (peopleKnowingSecret[currentDay + forget] -
28 newPeoplePerDay[currentDay] + MOD) % MOD;
29
30 // Calculate when these people can start sharing the secret
31 int shareStartDay = currentDay + delay;
32
33 // These people can share from (currentDay + delay) to (currentDay + forget - 1)
34 while (shareStartDay < currentDay + forget) {
35 // Each person shares with one new person per day during their sharing period
36 newPeoplePerDay[shareStartDay] = (newPeoplePerDay[shareStartDay] +
37 newPeoplePerDay[currentDay]) % MOD;
38 ++shareStartDay;
39 }
40 }
41 }
42
43 // Calculate total people who know the secret on day n
44 // Sum up all the net changes from day 1 to day n
45 long totalPeopleKnowing = 0;
46 for (int day = 1; day <= n; ++day) {
47 totalPeopleKnowing = (totalPeopleKnowing + peopleKnowingSecret[day]) % MOD;
48 }
49
50 return (int) totalPeopleKnowing;
51 }
52}
53
1using ll = long long;
2const int MOD = 1e9 + 7;
3
4class Solution {
5public:
6 int peopleAwareOfSecret(int n, int delay, int forget) {
7 // Allocate extra space to avoid boundary issues
8 int maxDays = (n << 1) + 10;
9
10 // deltaKnowers[i]: net change in number of people who know the secret on day i
11 vector<ll> deltaKnowers(maxDays);
12
13 // newSpreaders[i]: number of new people who start spreading the secret on day i
14 vector<ll> newSpreaders(maxDays);
15
16 // Initially, one person knows the secret on day 1
17 newSpreaders[1] = 1;
18
19 // Process each day from 1 to n
20 for (int day = 1; day <= n; ++day) {
21 // Skip if no new spreaders on this day
22 if (!newSpreaders[day]) continue;
23
24 // People who start spreading on this day also start knowing the secret
25 deltaKnowers[day] = (deltaKnowers[day] + newSpreaders[day]) % MOD;
26
27 // These people will forget the secret after 'forget' days
28 deltaKnowers[day + forget] = (deltaKnowers[day + forget] - newSpreaders[day] + MOD) % MOD;
29
30 // Calculate when these people can start spreading
31 // They can spread from day + delay until day + forget - 1
32 int startSpreadingDay = day + delay;
33 while (startSpreadingDay < day + forget) {
34 // Each person who starts spreading on 'day' will cause one new person
35 // to start spreading on each day in their spreading window
36 newSpreaders[startSpreadingDay] = (newSpreaders[startSpreadingDay] + newSpreaders[day]) % MOD;
37 ++startSpreadingDay;
38 }
39 }
40
41 // Calculate total number of people who know the secret on day n
42 // This is the cumulative sum of all delta changes up to day n
43 int totalPeopleKnowing = 0;
44 for (int day = 1; day <= n; ++day) {
45 totalPeopleKnowing = (totalPeopleKnowing + deltaKnowers[day]) % MOD;
46 }
47
48 return totalPeopleKnowing;
49 }
50};
51
1/**
2 * Calculates the number of people aware of a secret on day n
3 * @param n - The target day to check how many people know the secret
4 * @param delay - Number of days before a person can start sharing the secret
5 * @param forget - Number of days after which a person forgets the secret
6 * @returns The number of people who know the secret on day n, modulo 10^9 + 7
7 */
8function peopleAwareOfSecret(n: number, delay: number, forget: number): number {
9 // dp[i] represents the number of people who learned the secret on day i
10 const dp: bigint[] = new Array(n + 1).fill(0n);
11
12 // On day 1, one person knows the secret
13 dp[1] = 1n;
14
15 // Calculate for each day from 2 to n
16 for (let currentDay = 2; currentDay <= n; currentDay++) {
17 let newPeopleToday = 0n;
18
19 // People who can share the secret today are those who:
20 // 1. Learned it at least 'delay' days ago (currentDay - delay)
21 // 2. Haven't forgotten it yet (learned within last 'forget' days)
22 const earliestSharingDay = currentDay - forget + 1;
23 const latestSharingDay = currentDay - delay;
24
25 for (let learningDay = earliestSharingDay; learningDay <= latestSharingDay; learningDay++) {
26 if (learningDay > 0) {
27 newPeopleToday += dp[learningDay];
28 }
29 }
30
31 dp[currentDay] = newPeopleToday;
32 }
33
34 // Count all people who still remember the secret on day n
35 let totalPeopleAware = 0n;
36 const dayAfterTarget = n + 1;
37
38 // People who remember are those who learned within the last 'forget' days
39 const earliestRememberingDay = dayAfterTarget - forget;
40 const latestRememberingDay = dayAfterTarget - 1;
41
42 for (let learningDay = earliestRememberingDay; learningDay <= latestRememberingDay; learningDay++) {
43 if (learningDay > 0) {
44 totalPeopleAware += dp[learningDay];
45 }
46 }
47
48 // Return the result modulo 10^9 + 7
49 const MOD = BigInt(10 ** 9 + 7);
50 return Number(totalPeopleAware % MOD);
51}
52
Time and Space Complexity
Time Complexity: O(n * forget)
The algorithm uses nested loops where:
- The outer loop runs from
1
ton
, iteratingn
times - For each person who knows the secret at day
i
(whencnt[i] > 0
), the inner while loop runs fromi + delay
toi + forget - 1
- This inner loop executes
forget - delay
times, which is at mostforget - 1
times - In the worst case, every day could have people knowing the secret, leading to
O(n * forget)
operations
Space Complexity: O(n)
The algorithm uses:
- Two arrays
d
andcnt
, each of sizem = (n << 1) + 10
, which is approximately2n + 10
- Since
m
is linearly proportional ton
, the space complexity isO(n)
- No additional data structures that scale with input size are used
Learn more about how to find time and space complexity quickly.
Common Pitfalls
1. Off-by-One Error in Sharing Period
Pitfall: Incorrectly including the day when a person forgets the secret in their sharing period. The problem explicitly states that a person cannot share on the same day they forget.
Incorrect Implementation:
# Wrong: includes day i + forget
for sharing_day in range(start_sharing_day, stop_sharing_day + 1):
new_people_each_day[sharing_day] += new_people_each_day[day]
Correct Implementation:
# Correct: stops at day i + forget - 1
for sharing_day in range(start_sharing_day, stop_sharing_day):
new_people_each_day[sharing_day] += new_people_each_day[day]
2. Insufficient Buffer Size Leading to Index Out of Bounds
Pitfall: Using exactly n
or n + forget
as array size, which causes index errors when accessing day + forget
positions.
Incorrect Implementation:
# Wrong: may cause index error people_knowing_secret = [0] * (n + 1) new_people_each_day = [0] * (n + 1)
Correct Implementation:
# Correct: provides sufficient buffer buffer_size = (n << 1) + 10 # or simply 2 * n + forget people_knowing_secret = [0] * buffer_size new_people_each_day = [0] * buffer_size
3. Forgetting to Apply Modulo Operation
Pitfall: Computing the final sum without applying modulo, which can cause integer overflow for large test cases.
Incorrect Implementation:
# Wrong: missing modulo
return sum(people_knowing_secret[:n + 1])
Correct Implementation:
# Correct: applies modulo
MOD = 10**9 + 7
return sum(people_knowing_secret[:n + 1]) % MOD
4. Misunderstanding the Difference Array Concept
Pitfall: Thinking the difference array directly represents the number of people who know the secret on each day. The actual count requires computing the cumulative sum.
Incorrect Implementation:
# Wrong: returns value at day n instead of cumulative sum return people_knowing_secret[n] % MOD
Correct Implementation:
# Correct: returns cumulative sum up to day n
return sum(people_knowing_secret[:n + 1]) % MOD
5. Incorrect Handling of Delay Period
Pitfall: Starting to share immediately or miscalculating when sharing begins.
Key Points to Remember:
- A person discovers the secret on day
i
- They start sharing on day
i + delay
(noti + delay - 1
ori + delay + 1
) - They stop sharing on day
i + forget - 1
(the day before they forget)
What are the most two important steps in writing a depth first search function? (Select 2)
Recommended Readings
Queue Intro Think of the last time you stood in line to buy movie tickets The first person in line gets their ticket first and any newcomers join the end of the line This system where the first person to arrive is the first to be served is a queue in real
What is Dynamic Programming Prerequisite DFS problems dfs_intro Backtracking problems backtracking Memoization problems memoization_intro Pruning problems backtracking_pruning Dynamic programming is an algorithmic optimization technique that breaks down a complicated problem into smaller overlapping sub problems in a recursive manner and uses solutions to the sub problems to construct a solution
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Want a Structured Path to Master System Design Too? Don’t Miss This!