Facebook Pixel

1744. Can You Eat Your Favorite Candy on Your Favorite Day

Problem Description

You have different types of candies arranged in order (type 0, type 1, type 2, etc.). The array candiesCount[i] tells you how many candies of type i you have.

You play a candy-eating game with these rules:

  • You start eating on day 0
  • You must eat candies in order by type (you cannot eat any candy of type i until you've eaten ALL candies of types 0 through i-1)
  • You must eat at least 1 candy per day
  • You can eat multiple types of candy on the same day (as long as you follow the type order rule)

For each query [favoriteType, favoriteDay, dailyCap], you want to know: Can you eat at least one candy of favoriteType on exactly favoriteDay while never eating more than dailyCap candies on any single day?

The solution uses prefix sums to track candy positions. For each query:

  • Calculate s: prefix sum array where s[i] = total candies of types 0 through i-1
  • Find the range of candies you could potentially eat by favoriteDay:
    • Minimum: eating 1 candy per day means you'll have eaten day candies by then
    • Maximum: eating dailyCap per day means you could eat up to (day + 1) * mx candies
  • Check if this range overlaps with the position of favoriteType candies:
    • favoriteType candies occupy positions from s[t] to s[t+1] - 1
    • You can eat favoriteType on favoriteDay if your eating range [least, most] overlaps with candy positions [s[t], s[t+1] - 1]
    • This happens when least < s[t + 1] and most > s[t]

Return a boolean array where each element indicates whether the corresponding query is achievable.

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

Intuition

The key insight is to think about candies as being arranged in a single line, where each candy has a position number. Since we must eat candies in type order, candy type 0 occupies positions 0 to candiesCount[0] - 1, candy type 1 occupies positions candiesCount[0] to candiesCount[0] + candiesCount[1] - 1, and so on.

To determine if we can eat a specific type on a specific day, we need to figure out:

  1. What range of positions could we have eaten by that day?
  2. Does this range overlap with the positions of our favorite type?

For the range of positions we could eat by day d:

  • Minimum position: If we eat only 1 candy per day (the minimum required), by day d we will have eaten exactly d candies (since we start on day 0). So the next candy we eat on day d would be at position d.
  • Maximum position: If we eat dailyCap candies every day, by the end of day d we could have eaten up to (d + 1) * dailyCap candies total. This means on day d, we could potentially be eating candy at position (d + 1) * dailyCap - 1.

Using prefix sums makes it easy to find where each candy type starts and ends in our imaginary line. If s[i] represents the total number of candies of types 0 through i-1, then:

  • Candy type t starts at position s[t]
  • Candy type t ends at position s[t + 1] - 1

The final check becomes simple: Can we reach at least the start of our favorite type (s[t]) but not go past its end (s[t + 1] - 1)? This translates to checking if our eating range [least, most] has any overlap with the candy type's range [s[t], s[t + 1] - 1]. Two ranges overlap when the minimum of one is less than the maximum of the other, which gives us the conditions least < s[t + 1] and most > s[t].

Learn more about Prefix Sum patterns.

Solution Approach

The implementation uses a prefix sum array to efficiently track candy positions and determine if we can eat a specific type on a specific day.

Step 1: Build Prefix Sum Array

s = list(accumulate(candiesCount, initial=0))

We use Python's accumulate function with initial=0 to create a prefix sum array where:

  • s[0] = 0 (no candies before type 0)
  • s[1] = candiesCount[0] (total candies of type 0)
  • s[2] = candiesCount[0] + candiesCount[1] (total candies of types 0 and 1)
  • And so on...

This tells us that candy type t occupies positions from s[t] to s[t+1] - 1.

Step 2: Process Each Query

for t, day, mx in queries:

For each query, we extract:

  • t: the favorite candy type
  • day: the day we want to eat this type
  • mx: the maximum candies we can eat per day (dailyCap)

Step 3: Calculate Eating Range

least, most = day, (day + 1) * mx
  • least = day: The minimum position we could be at on day day (eating 1 candy per day, we'd have eaten day candies by day day)
  • most = (day + 1) * mx: The maximum position we could reach (eating mx candies each day for day + 1 days total)

Step 4: Check Range Overlap

ans.append(least < s[t + 1] and most > s[t])

We check if our eating range [least, most) overlaps with candy type t's range [s[t], s[t+1]):

  • least < s[t + 1]: We haven't already passed all candies of type t
  • most > s[t]: We can reach at least the first candy of type t

Both conditions must be true for us to be able to eat candy type t on day day.

Time Complexity: O(n + q) where n is the length of candiesCount and q is the number of queries. Building the prefix sum takes O(n) and each query is processed in O(1).

Space Complexity: O(n) for storing the prefix sum array.

Ready to land your dream job?

Unlock your dream job with a 3-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through a small example to illustrate the solution approach.

Given:

  • candiesCount = [5, 2, 6, 4, 1]
  • queries = [[3, 1, 2], [4, 10, 3], [2, 8, 8]]

Step 1: Build the prefix sum array

First, we create the prefix sum array s:

  • s[0] = 0 (no candies before type 0)
  • s[1] = 5 (5 candies of type 0)
  • s[2] = 7 (5 + 2 = 7 candies of types 0-1)
  • s[3] = 13 (5 + 2 + 6 = 13 candies of types 0-2)
  • s[4] = 17 (5 + 2 + 6 + 4 = 17 candies of types 0-3)
  • s[5] = 18 (5 + 2 + 6 + 4 + 1 = 18 total candies)

So s = [0, 5, 7, 13, 17, 18]

This means:

  • Type 0 candies are at positions 0-4
  • Type 1 candies are at positions 5-6
  • Type 2 candies are at positions 7-12
  • Type 3 candies are at positions 13-16
  • Type 4 candies are at position 17

Step 2: Process each query

Query 1: [3, 1, 2] - Can we eat type 3 on day 1 with dailyCap = 2?

  • Calculate eating range:
    • least = 1 (minimum position on day 1)
    • most = (1 + 1) * 2 = 4 (maximum position we could reach)
  • Type 3 candies are at positions 13-16 (s[3] = 13 to s[4] - 1 = 16)
  • Check overlap: least < s[4]? → 1 < 17 ✓ AND most > s[3]? → 4 > 13
  • Result: False (we can't reach position 13 by day 1)

Query 2: [4, 10, 3] - Can we eat type 4 on day 10 with dailyCap = 3?

  • Calculate eating range:
    • least = 10 (minimum position on day 10)
    • most = (10 + 1) * 3 = 33 (maximum position we could reach)
  • Type 4 candies are at position 17 (s[4] = 17 to s[5] - 1 = 17)
  • Check overlap: least < s[5]? → 10 < 18 ✓ AND most > s[4]? → 33 > 17
  • Result: True (we can reach position 17 on day 10)

Query 3: [2, 8, 8] - Can we eat type 2 on day 8 with dailyCap = 8?

  • Calculate eating range:
    • least = 8 (minimum position on day 8)
    • most = (8 + 1) * 8 = 72 (maximum position we could reach)
  • Type 2 candies are at positions 7-12 (s[2] = 7 to s[3] - 1 = 12)
  • Check overlap: least < s[3]? → 8 < 13 ✓ AND most > s[2]? → 72 > 7
  • Result: True (positions 8-12 are within our reach on day 8)

Final Answer: [False, True, True]

Solution Implementation

1class Solution:
2    def canEat(self, candiesCount: List[int], queries: List[List[int]]) -> List[bool]:
3        from itertools import accumulate
4        from typing import List
5      
6        # Calculate prefix sum of candies (cumulative sum)
7        # prefix_sum[i] represents total candies from type 0 to type i-1
8        prefix_sum = list(accumulate(candiesCount, initial=0))
9      
10        result = []
11      
12        for favorite_type, favorite_day, daily_cap in queries:
13            # Minimum candies eaten: eat 1 candy per day until favorite_day
14            min_candies_eaten = favorite_day
15          
16            # Maximum candies eaten: eat daily_cap candies per day through favorite_day
17            max_candies_eaten = (favorite_day + 1) * daily_cap
18          
19            # Check if we can eat favorite_type candy on favorite_day
20            # We need to have eaten enough to reach favorite_type candies (> prefix_sum[favorite_type])
21            # But not so many that we've already consumed all of them (< prefix_sum[favorite_type + 1])
22            can_eat_favorite = (min_candies_eaten < prefix_sum[favorite_type + 1] and 
23                               max_candies_eaten > prefix_sum[favorite_type])
24          
25            result.append(can_eat_favorite)
26      
27        return result
28
1class Solution {
2    public boolean[] canEat(int[] candiesCount, int[][] queries) {
3        // Get the number of candy types
4        int numCandyTypes = candiesCount.length;
5      
6        // Build prefix sum array to store cumulative candy counts
7        // prefixSum[i] represents total candies from type 0 to type i-1
8        long[] prefixSum = new long[numCandyTypes + 1];
9        for (int i = 0; i < numCandyTypes; i++) {
10            prefixSum[i + 1] = prefixSum[i] + candiesCount[i];
11        }
12      
13        // Process each query
14        int numQueries = queries.length;
15        boolean[] result = new boolean[numQueries];
16      
17        for (int i = 0; i < numQueries; i++) {
18            // Extract query parameters
19            int favoriteType = queries[i][0];
20            int favoriteDay = queries[i][1];
21            int dailyCap = queries[i][2];
22          
23            // Calculate the range of candies that can be eaten
24            // Minimum: eat 1 candy per day, so by favoriteDay we eat at least favoriteDay candies
25            long minCandiesEaten = favoriteDay;
26          
27            // Maximum: eat dailyCap candies per day for (favoriteDay + 1) days
28            // +1 because days are 0-indexed, so day 0 means 1 day
29            long maxCandiesEaten = (long)(favoriteDay + 1) * dailyCap;
30          
31            // Check if we can reach favorite type candy
32            // We can eat favorite type if:
33            // 1. minCandiesEaten < total candies up to and including favoriteType
34            // 2. maxCandiesEaten > total candies before favoriteType
35            result[i] = minCandiesEaten < prefixSum[favoriteType + 1] && 
36                       maxCandiesEaten > prefixSum[favoriteType];
37        }
38      
39        return result;
40    }
41}
42
1using ll = long long;
2
3class Solution {
4public:
5    vector<bool> canEat(vector<int>& candiesCount, vector<vector<int>>& queries) {
6        int n = candiesCount.size();
7      
8        // Build prefix sum array to store cumulative candy counts
9        // prefixSum[i] represents total candies from type 0 to type i-1
10        vector<ll> prefixSum(n + 1);
11        for (int i = 0; i < n; ++i) {
12            prefixSum[i + 1] = prefixSum[i] + candiesCount[i];
13        }
14      
15        vector<bool> result;
16      
17        // Process each query
18        for (auto& query : queries) {
19            int favoriteType = query[0];
20            int favoriteDay = query[1];
21            int dailyCap = query[2];
22          
23            // Calculate the range of candies we can eat
24            // Minimum: eat 1 candy per day, need to eat at least 'favoriteDay' candies before reaching favorite type
25            ll minCandiesEaten = favoriteDay;
26          
27            // Maximum: eat 'dailyCap' candies per day for (favoriteDay + 1) days
28            ll maxCandiesEaten = 1ll * (favoriteDay + 1) * dailyCap;
29          
30            // Check if we can eat favorite type candy on the given day
31            // We can eat it if:
32            // 1. We haven't eaten all candies of favorite type yet (minCandiesEaten < total candies up to and including favorite type)
33            // 2. We have eaten enough to reach favorite type (maxCandiesEaten > total candies before favorite type)
34            bool canEatFavorite = (minCandiesEaten < prefixSum[favoriteType + 1]) && 
35                                  (maxCandiesEaten > prefixSum[favoriteType]);
36          
37            result.emplace_back(canEatFavorite);
38        }
39      
40        return result;
41    }
42};
43
1type ll = number;
2
3function canEat(candiesCount: number[], queries: number[][]): boolean[] {
4    const n: number = candiesCount.length;
5  
6    // Build prefix sum array to store cumulative candy counts
7    // prefixSum[i] represents total candies from type 0 to type i-1
8    const prefixSum: ll[] = new Array(n + 1).fill(0);
9    for (let i = 0; i < n; i++) {
10        prefixSum[i + 1] = prefixSum[i] + candiesCount[i];
11    }
12  
13    const result: boolean[] = [];
14  
15    // Process each query
16    for (const query of queries) {
17        const favoriteType: number = query[0];
18        const favoriteDay: number = query[1];
19        const dailyCap: number = query[2];
20      
21        // Calculate the range of candies we can eat
22        // Minimum: eat 1 candy per day, need to eat at least 'favoriteDay' candies before reaching favorite type
23        const minCandiesEaten: ll = favoriteDay;
24      
25        // Maximum: eat 'dailyCap' candies per day for (favoriteDay + 1) days
26        const maxCandiesEaten: ll = (favoriteDay + 1) * dailyCap;
27      
28        // Check if we can eat favorite type candy on the given day
29        // We can eat it if:
30        // 1. We haven't eaten all candies of favorite type yet (minCandiesEaten < total candies up to and including favorite type)
31        // 2. We have eaten enough to reach favorite type (maxCandiesEaten > total candies before favorite type)
32        const canEatFavorite: boolean = (minCandiesEaten < prefixSum[favoriteType + 1]) && 
33                                        (maxCandiesEaten > prefixSum[favoriteType]);
34      
35        result.push(canEatFavorite);
36    }
37  
38    return result;
39}
40

Time and Space Complexity

Time Complexity: O(n + q) where n is the length of candiesCount and q is the length of queries.

  • Computing the prefix sum using accumulate() takes O(n) time to iterate through all elements in candiesCount.
  • Processing each query takes O(1) time as we're only performing constant-time operations (arithmetic calculations and array indexing).
  • Since we process q queries, the query processing takes O(q) time in total.
  • Overall time complexity: O(n) + O(q) = O(n + q).

Space Complexity: O(n) where n is the length of candiesCount.

  • The prefix sum array s stores n + 1 elements (including the initial 0), requiring O(n) space.
  • The answer list ans stores q boolean values, but this is considered part of the output and typically not counted in auxiliary space complexity.
  • Variables least, most, t, day, and mx use O(1) space.
  • Overall auxiliary space complexity: O(n).

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. Off-by-One Error in Day Calculation

Pitfall: A common mistake is confusing the day indexing. Since we start eating on day 0, by day d we have had d + 1 days to eat candies. Many developers incorrectly calculate the maximum candies eaten as day * dailyCap instead of (day + 1) * dailyCap.

Wrong Implementation:

max_candies_eaten = day * daily_cap  # WRONG! Misses one day

Correct Implementation:

max_candies_eaten = (day + 1) * daily_cap  # Correct: includes day 0 through day d

2. Incorrect Range Overlap Logic

Pitfall: When checking if two ranges overlap, developers often use incorrect comparison operators or apply wrong logic. The ranges are [min_eaten, max_eaten) and [prefix_sum[t], prefix_sum[t+1]).

Wrong Implementation:

# Using <= and >= incorrectly
can_eat = min_candies_eaten <= prefix_sum[favorite_type + 1] and max_candies_eaten >= prefix_sum[favorite_type]

Correct Implementation:

# Proper range overlap: first range hasn't passed second AND can reach second
can_eat = min_candies_eaten < prefix_sum[favorite_type + 1] and max_candies_eaten > prefix_sum[favorite_type]

3. Forgetting Edge Case of Eating 1 Candy Per Day

Pitfall: Some developers calculate the minimum position incorrectly by assuming we must eat at least one candy on the favorite day itself, using day + 1 as the minimum.

Wrong Implementation:

min_candies_eaten = day + 1  # WRONG! This assumes we've eaten day+1 candies by day d

Correct Implementation:

min_candies_eaten = day  # Correct: eating 1 per day, we've eaten exactly 'day' candies by day 'day'

4. Integer Overflow in Maximum Calculation

Pitfall: For large values of favorite_day and daily_cap, the multiplication (day + 1) * daily_cap might overflow in languages with fixed integer sizes. While Python handles arbitrary precision integers, this is a concern in languages like Java or C++.

Solution for Other Languages:

# In Python, this is handled automatically
max_candies_eaten = (favorite_day + 1) * daily_cap

# In Java/C++, use long/long long:
# long maxCandiesEaten = (long)(favoriteDay + 1) * dailyCap;

5. Misunderstanding Candy Position Indexing

Pitfall: Confusing 0-based candy positions with 1-based counting. The first candy (position 0) is eaten on day 0 when we've eaten 0 candies previously.

Example to Remember:

  • Day 0: Can eat candies at positions [0, dailyCap)
  • Day 1: Can eat candies at positions [1, 2*dailyCap)
  • Day d: Can eat candies at positions [d, (d+1)*dailyCap)

The minimum position on day d is d (eating 1 per day), not d+1.

Discover Your Strengths and Weaknesses: Take Our 3-Minute Quiz to Tailor Your Study Plan:

Which data structure is used to implement recursion?


Recommended Readings

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

Load More