title: Can You Eat Your Favorite Candy on Your Favorite Day?
slug: can-you-eat-your-favorite-candy-on-your-favorite-day
difficulty: medium
leetcode_id: 1744
leetcode_url: https://leetcode.com/problems/can-you-eat-your-favorite-candy-on-your-favorite-day/
categories:
  - arrays
patterns:
  - slug: prefix-sum
    is_optimal: true

function_signature: "def can_eat(candies_count: list[int], queries: list[list[int]]) -> list[bool]:"

test_cases:
  visible:
    - input: { candies_count: [7, 4, 5, 3, 8], queries: [[0, 2, 2], [4, 2, 4], [2, 13, 1000000000]] }
      expected: [true, false, true]
    - input: { candies_count: [5, 2, 6, 4, 1], queries: [[3, 1, 2], [4, 10, 3], [3, 10, 100], [4, 100, 30], [1, 3, 1]] }
      expected: [false, true, true, false, false]
  hidden:
    - input: { candies_count: [1], queries: [[0, 0, 1]] }
      expected: [true]
    - input: { candies_count: [5, 5], queries: [[0, 0, 5], [1, 4, 1]] }
      expected: [true, true]
    - input: { candies_count: [10, 10], queries: [[0, 5, 1], [1, 5, 1]] }
      expected: [true, true]

description: |
  You are given a **(0-indexed)** array of positive integers `candiesCount` where `candiesCount[i]` represents the number of candies of the i<sup>th</sup> type you have. You are also given a 2D array `queries` where `queries[i] = [favoriteType_i, favoriteDay_i, dailyCap_i]`.

  You play a game with the following rules:

  - You start eating candies on day `0`.
  - You **cannot** eat any candy of type `i` unless you have eaten **all** candies of type `i - 1`.
  - You must eat **at least one** candy per day until you have eaten all the candies.

  Construct a boolean array `answer` such that `answer.length == queries.length` and `answer[i]` is `true` if you can eat a candy of type `favoriteType_i` on day `favoriteDay_i` without eating **more than** `dailyCap_i` candies on **any** day, and `false` otherwise.

  Note that you can eat different types of candy on the same day, provided that you follow rule 2.

  Return *the constructed array* `answer`.

constraints: |
  - `1 <= candiesCount.length <= 10^5`
  - `1 <= candiesCount[i] <= 10^5`
  - `1 <= queries.length <= 10^5`
  - `queries[i].length == 3`
  - `0 <= favoriteType_i < candiesCount.length`
  - `0 <= favoriteDay_i <= 10^9`
  - `1 <= dailyCap_i <= 10^9`

examples:
  - input: "candiesCount = [7,4,5,3,8], queries = [[0,2,2],[4,2,4],[2,13,1000000000]]"
    output: "[true,false,true]"
    explanation: |
      1. If you eat 2 candies (type 0) on day 0 and 2 candies (type 0) on day 1, you will eat a candy of type 0 on day 2.
      2. You can eat at most 4 candies each day. If you eat 4 candies every day, you will eat 4 candies (type 0) on day 0 and 4 candies (type 0 and type 1) on day 1. On day 2, you can only eat 4 candies (type 1 and type 2), so you cannot eat a candy of type 4 on day 2.
      3. If you eat 1 candy each day, you will eat a candy of type 2 on day 13.
  - input: "candiesCount = [5,2,6,4,1], queries = [[3,1,2],[4,10,3],[3,10,100],[4,100,30],[1,3,1]]"
    output: "[false,true,true,false,false]"
    explanation: "Each query is evaluated independently based on the range of candies that can be eaten by the given day."

explanation:
  intuition: |
    Imagine you're eating through a long sequence of candies arranged by type. Types are eaten in order (you must finish all type 0 before starting type 1, and so on). Each day you can eat between 1 and `dailyCap` candies.

    The key insight is that on any given day, there's a **range of possible candies** you could be eating, depending on how fast or slow you eat:

    - **Minimum candies eaten**: If you eat exactly 1 candy per day, by day `d` you've eaten `d + 1` candies (days are 0-indexed).
    - **Maximum candies eaten**: If you eat `dailyCap` candies every day, by day `d` you've eaten `(d + 1) * dailyCap` candies.

    For you to eat a candy of your favorite type on day `d`, there must be **overlap** between:
    1. The range of candies you *could* have eaten by day `d`: `[d + 1, (d + 1) * dailyCap]`
    2. The range of candies that belong to your favorite type: `[prefix[type - 1] + 1, prefix[type]]`

    If these two ranges overlap, you can adjust your eating speed to hit a candy of your favorite type exactly on that day. If they don't overlap, it's impossible.

  approach: |
    We solve this using **Prefix Sums** to precompute candy ranges efficiently:

    **Step 1: Build the prefix sum array**

    - Create `prefix[i]` representing the total number of candies from type `0` through type `i`
    - This lets us quickly determine where each candy type begins and ends in the sequence

    &nbsp;

    **Step 2: For each query, determine the candy range for the favorite type**

    - `candies_before`: Total candies before the favorite type = `prefix[type - 1]` (or `0` if type is `0`)
    - `candies_up_to`: Total candies up to and including the favorite type = `prefix[type]`
    - The favorite type occupies candies in the range `(candies_before, candies_up_to]`

    &nbsp;

    **Step 3: Determine the range of candies reachable on the favorite day**

    - `min_candies`: Eating 1 candy per day means `day + 1` candies eaten by end of day (0-indexed)
    - `max_candies`: Eating at maximum capacity means `(day + 1) * dailyCap` candies eaten

    &nbsp;

    **Step 4: Check for overlap between the two ranges**

    - Two ranges `[a, b]` and `[c, d]` overlap if `a <= d` and `c <= b`
    - If `min_candies <= candies_up_to` AND `candies_before < max_candies`, return `true`
    - Otherwise, return `false`

    &nbsp;

    The prefix sum allows O(1) range lookups per query, making the overall solution efficient.

  common_pitfalls:
    - title: Off-by-One Errors with Days
      description: |
        Days are 0-indexed, meaning on day 0 you've had 1 opportunity to eat (not 0). By the end of day `d`, you've eaten at minimum `d + 1` candies, not `d`.

        This off-by-one error is easy to make and will cause incorrect results for edge cases where the day number is critical.
      wrong_approach: "Using `day` instead of `day + 1` for minimum candies"
      correct_approach: "Remember day 0 means 1 day of eating, so use `day + 1`"

    - title: Integer Overflow
      description: |
        With `favoriteDay <= 10^9` and `dailyCap <= 10^9`, the product `(day + 1) * dailyCap` can exceed 32-bit integer limits (up to 10^18).

        In Python this isn't an issue, but in other languages you'd need to use 64-bit integers or handle overflow explicitly.
      wrong_approach: "Using 32-bit integers for max_candies calculation"
      correct_approach: "Use 64-bit integers (or Python's arbitrary precision)"

    - title: Boundary Confusion in Range Overlap
      description: |
        The candy ranges use different boundary conventions:
        - Candies reachable: `[min_candies, max_candies]` (inclusive)
        - Favorite type range: `(candies_before, candies_up_to]` (exclusive start, inclusive end)

        The overlap check needs to account for this. The first candy of the favorite type is `candies_before + 1`, so we check `candies_before < max_candies` (strict inequality).
      wrong_approach: "Using `candies_before <= max_candies` with inclusive boundaries"
      correct_approach: "Use strict inequality for the exclusive boundary"

  key_takeaways:
    - "**Prefix sums for range queries**: Precomputing cumulative sums allows O(1) lookups for any range, turning O(n) per query into O(1)"
    - "**Range overlap pattern**: Many problems reduce to checking if two intervals overlap — master the condition `a <= d and c <= b`"
    - "**Model the problem mathematically**: Converting 'can I eat candy X on day Y' into range overlap makes the solution clear"
    - "**Watch for off-by-one errors**: 0-indexed vs 1-indexed, inclusive vs exclusive boundaries — these details matter"

  time_complexity: "O(n + q). Building the prefix sum takes O(n), and answering each of the q queries takes O(1)."
  space_complexity: "O(n). We store the prefix sum array of size n. The output array of size q is required regardless."

solutions:
  - approach_name: Prefix Sum with Range Overlap
    is_optimal: true
    code: |
      def canEat(candiesCount: list[int], queries: list[list[int]]) -> list[bool]:
          n = len(candiesCount)

          # Build prefix sum: prefix[i] = total candies from type 0 to type i
          prefix = [0] * n
          prefix[0] = candiesCount[0]
          for i in range(1, n):
              prefix[i] = prefix[i - 1] + candiesCount[i]

          result = []
          for favorite_type, favorite_day, daily_cap in queries:
              # Candies of favorite type occupy the range (candies_before, candies_up_to]
              candies_before = prefix[favorite_type - 1] if favorite_type > 0 else 0
              candies_up_to = prefix[favorite_type]

              # By end of favorite_day, we've eaten between min and max candies
              # (days are 0-indexed, so day 0 means 1 day of eating)
              min_candies = favorite_day + 1  # eat 1 candy per day
              max_candies = (favorite_day + 1) * daily_cap  # eat at max capacity

              # Check if ranges overlap:
              # We can eat favorite type if our reachable range overlaps the type's range
              # Overlap condition: min_candies <= candies_up_to AND candies_before < max_candies
              can_eat = min_candies <= candies_up_to and candies_before < max_candies
              result.append(can_eat)

          return result
    explanation: |
      **Time Complexity:** O(n + q) — O(n) to build prefix sum, O(1) per query.

      **Space Complexity:** O(n) — For the prefix sum array.

      We precompute the cumulative candy count, then for each query we check if the range of candies reachable on the given day overlaps with the range of candies belonging to the favorite type. The key insight is that eating speed determines a range, and we need that range to intersect with our target.
