You are given an array candiesCount
where candiesCount[i]
represents the number of candies of the ith
type. You are also given a 2D array queries
, where each query is of the form [favoriteType, favoriteDay, dailyCap]
:
favoriteType
: The type of candy you like (0-indexed).favoriteDay
: The day (0-indexed) you want to eat your favorite candy.dailyCap
: The maximum number of candies you can eat each day.
Starting from day 0, you eat at least one candy per day and at most dailyCap
candies per day. You must eat all candies of type 0 before eating type 1, all candies of type 1 before type 2, and so on (i.e., you eat candies in order of type).
For each query, determine if it is possible to eat a candy of your favoriteType
on your favoriteDay
given the constraints above. Return an array of boolean values, one for each query.
Key constraints:
dailyCap
candies per day.
To solve this problem, let's first think about what it means to eat a candy of a specific type on a specific day. Since you must eat candies in order, you can only eat type i
after finishing all candies of types before i
. For any day, you can eat between 1 and dailyCap
candies per day, so the total number of candies you could have eaten by day favoriteDay
is between favoriteDay + 1
(if you eat 1 per day) and (favoriteDay + 1) * dailyCap
(if you eat the max each day).
The brute-force approach would simulate eating candies day by day, but this would be too slow for large inputs. Instead, we can use prefix sums to quickly calculate how many candies are before your favorite type and how many candies you need to eat to start and finish that type.
The key insight is to check if there is any overlap between the range of candies you could have eaten by favoriteDay
and the range of candies corresponding to your favorite type.
Let's break down the solution step-by-step:
prefix[i]
is the total number of candies of types 0
to i-1
.i
.favoriteType = t
, favoriteDay = d
, dailyCap = cap
.d
is [d + 1, (d + 1) * cap]
.t
is [prefix[t] + 1, prefix[t] + candiesCount[t]]
.d
, these two ranges must overlap.[a1, a2]
and [b1, b2]
overlap if max(a1, b1) <= min(a2, b2)
.True
for this query; else, False
.This approach is efficient because prefix sums allow constant-time range queries, and we avoid simulating each day.
Consider the following input:
candiesCount = [7, 4, 5, 3, 8]
queries = [[0,2,2], [4,2,4], [2,13,1000000000]]
Step 1: Compute Prefix Sums
prefix = [0, 7, 11, 16, 19, 27]
Query 1: [0,2,2]
- favoriteType = 0
, favoriteDay = 2
, dailyCap = 2
- Candies eaten by day 2: [3, 6]
- Type 0 candies: [1, 7]
- Overlap: max(3,1) = 3
, min(6,7) = 6
, so 3 <= 6
⇒ True
Query 2: [4,2,4]
- Type 4 starts at prefix[4]+1 = 20
, ends at 27
- By day 2: [3,12]
- Overlap: max(3,20) = 20
, min(12,27) = 12
, so 20 > 12
⇒ False
Query 3: [2,13,1000000000]
- Type 2 starts at prefix[2]+1 = 12
, ends at 16
- By day 13: [14, 14000000000]
- Overlap: max(14,12) = 14
, min(14000000000,16) = 16
, so 14 <= 16
⇒ True
Final Output: [True, False, True]
Brute-Force Approach:
N
is the number of days, which can be very large.This makes the optimized solution very efficient, even for large input sizes.
In this problem, we efficiently determine if it is possible to eat your favorite candy on your favorite day by using prefix sums to quickly compute how many candies you could have eaten by a certain day and how many candies are required to reach your favorite type. By checking for overlap between possible candies eaten and the candies of your favorite type, we answer each query in constant time. This approach is both elegant and optimal for the problem's constraints.
from typing import List
class Solution:
def canEat(self, candiesCount: List[int], queries: List[List[int]]) -> List[bool]:
# Compute prefix sums
prefix = [0]
for count in candiesCount:
prefix.append(prefix[-1] + count)
result = []
for t, d, cap in queries:
# The earliest and latest candy number eaten on day d
min_candies = d + 1
max_candies = (d + 1) * cap
# The range of candies belonging to type t
type_start = prefix[t] + 1
type_end = prefix[t + 1]
# Check for overlap
can = not (max_candies < type_start or min_candies > type_end)
result.append(can)
return result
class Solution {
public:
vector<bool> canEat(vector<int>& candiesCount, vector<vector<int>>& queries) {
int n = candiesCount.size();
vector<long long> prefix(n + 1, 0);
for (int i = 0; i < n; ++i) {
prefix[i + 1] = prefix[i] + candiesCount[i];
}
vector<bool> result;
for (auto& q : queries) {
int t = q[0], d = q[1], cap = q[2];
long long min_candies = (long long)d + 1;
long long max_candies = (long long)(d + 1) * cap;
long long type_start = prefix[t] + 1;
long long type_end = prefix[t + 1];
bool can = !(max_candies < type_start || min_candies > type_end);
result.push_back(can);
}
return result;
}
};
class Solution {
public boolean[] canEat(int[] candiesCount, int[][] queries) {
int n = candiesCount.length;
long[] prefix = new long[n + 1];
for (int i = 0; i < n; ++i) {
prefix[i + 1] = prefix[i] + candiesCount[i];
}
boolean[] result = new boolean[queries.length];
for (int i = 0; i < queries.length; ++i) {
int t = queries[i][0], d = queries[i][1], cap = queries[i][2];
long min_candies = (long)d + 1;
long max_candies = (long)(d + 1) * cap;
long type_start = prefix[t] + 1;
long type_end = prefix[t + 1];
result[i] = !(max_candies < type_start || min_candies > type_end);
}
return result;
}
}
var canEat = function(candiesCount, queries) {
let n = candiesCount.length;
let prefix = new Array(n + 1).fill(0);
for (let i = 0; i < n; ++i) {
prefix[i + 1] = prefix[i] + candiesCount[i];
}
let result = [];
for (let q of queries) {
let t = q[0], d = q[1], cap = q[2];
let min_candies = d + 1;
let max_candies = (d + 1) * cap;
let type_start = prefix[t] + 1;
let type_end = prefix[t + 1];
let can = !(max_candies < type_start || min_candies > type_end);
result.push(can);
}
return result;
};