Facebook Pixel

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:

  1. 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.

  2. Forgetting Rule: A person forgets the secret exactly forget days after discovering it. Once forgotten, they can no longer share the secret.

  3. 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 to forget - 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.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

To solve this problem, we need to track two key pieces of information for each day:

  1. How many people discover the secret on that day (cnt[i])
  2. 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 day i + delay to day i + forget - 1
  • These cnt[i] people will forget the secret on day i + 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 day i
  • d[i]: Difference array to track people who know the secret

Implementation Steps:

  1. 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
  2. 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 day i will each share with one new person every day during their active sharing period [i + delay, i + forget - 1].

  3. 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 modulo 10^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) and d[5] -= 1 (forgets on day 5)
    • Will share on days 3 and 4
  • 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 Evaluator

Example 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 to 1+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 to 3+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 (now cnt[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 to n, iterating n times
  • For each person who knows the secret at day i (when cnt[i] > 0), the inner while loop runs from i + delay to i + forget - 1
  • This inner loop executes forget - delay times, which is at most forget - 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 and cnt, each of size m = (n << 1) + 10, which is approximately 2n + 10
  • Since m is linearly proportional to n, the space complexity is O(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 (not i + delay - 1 or i + delay + 1)
  • They stop sharing on day i + forget - 1 (the day before they forget)
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

What are the most two important steps in writing a depth first search function? (Select 2)


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More