The Diet Plan Performance problem asks you to evaluate a person's performance on a diet by analyzing their daily calorie intake. Given an integer array calories
where each element represents the calories consumed on a particular day, and three integers k
, lower
, and upper
, your task is to:
k
days (a sliding window of length k
).lower
, decrease the performance score by 1.upper
, increase the performance score by 1.lower
and upper
(inclusive), the score does not change.Constraints:
calories.length
≤ 105k
≤ calories.length
lower
and upper
can be any integerscalories
is an integer
The first idea that comes to mind is to check every possible sequence of k
days, sum their calories, and adjust the score accordingly. This brute-force approach would mean, for each starting index, summing up the next k
elements, which could be slow if calories
is large.
However, by noticing that each window overlaps with the previous one except for one element entering and one leaving, we can optimize the summing process. Instead of recalculating the sum from scratch for each window, we can keep a running sum: subtract the element that leaves the window and add the new one that enters. This is known as the sliding window technique and is much more efficient.
The key is to maintain a variable for the current sum and update it as the window slides, which reduces the time complexity from O(Nk) to O(N).
Let's break down the steps for solving this problem efficiently:
score
variable set to 0 and a window_sum
variable to keep track of the current sum.
k
elements in calories
and assign it to window_sum
.
window_sum
to lower
and upper
and update the score
accordingly.
i - k
) and add the element that's sliding in (at index i
), updating window_sum
efficiently.
window_sum
is less than lower
, greater than upper
, or in between, and update score
as needed.
score
.
This approach ensures each element is only added and subtracted once, resulting in a linear time solution.
Let's walk through an example:
calories = [1, 2, 3, 4, 5]
k = 3
lower = 6
upper = 8
Steps:
lower
, so score doesn't change (score = 0)Final score: 2
Brute-force approach:
k
elements: O(Nk) time, where N is the length of calories
.This efficiency is achieved by not recalculating sums from scratch for overlapping windows.
The Diet Plan Performance problem is an excellent example of how the sliding window technique can optimize a seemingly expensive brute-force process. By maintaining a running sum and updating it as the window moves forward, we achieve linear time complexity. This approach is both elegant and practical, making it suitable for large input sizes. The key insight is recognizing and exploiting the overlap between consecutive windows to avoid redundant calculations.
class Solution:
def dietPlanPerformance(self, calories, k, lower, upper):
score = 0
window_sum = sum(calories[:k])
n = len(calories)
# Evaluate the first window
if window_sum < lower:
score -= 1
elif window_sum > upper:
score += 1
# Slide the window
for i in range(k, n):
window_sum += calories[i] - calories[i - k]
if window_sum < lower:
score -= 1
elif window_sum > upper:
score += 1
return score
class Solution {
public:
int dietPlanPerformance(vector<int>& calories, int k, int lower, int upper) {
int score = 0;
int window_sum = 0;
int n = calories.size();
for (int i = 0; i < k; ++i) {
window_sum += calories[i];
}
// Evaluate first window
if (window_sum < lower) {
score--;
} else if (window_sum > upper) {
score++;
}
// Slide the window
for (int i = k; i < n; ++i) {
window_sum += calories[i] - calories[i - k];
if (window_sum < lower) {
score--;
} else if (window_sum > upper) {
score++;
}
}
return score;
}
};
class Solution {
public int dietPlanPerformance(int[] calories, int k, int lower, int upper) {
int score = 0;
int windowSum = 0;
int n = calories.length;
for (int i = 0; i < k; i++) {
windowSum += calories[i];
}
// Evaluate first window
if (windowSum < lower) {
score--;
} else if (windowSum > upper) {
score++;
}
// Slide the window
for (int i = k; i < n; i++) {
windowSum += calories[i] - calories[i - k];
if (windowSum < lower) {
score--;
} else if (windowSum > upper) {
score++;
}
}
return score;
}
}
var dietPlanPerformance = function(calories, k, lower, upper) {
let score = 0;
let windowSum = 0;
let n = calories.length;
for (let i = 0; i < k; i++) {
windowSum += calories[i];
}
// Evaluate first window
if (windowSum < lower) {
score--;
} else if (windowSum > upper) {
score++;
}
// Slide the window
for (let i = k; i < n; i++) {
windowSum += calories[i] - calories[i - k];
if (windowSum < lower) {
score--;
} else if (windowSum > upper) {
score++;
}
}
return score;
};