The best stretch to stay calm
A shop is open for n minutes. customers[i] people are served in minute i. In minutes
where moody[i] = 1 the owner is short-tempered and those customers leave unhappy; when
moody[i] = 0 they leave satisfied. Once a day the owner can stay calm for k
consecutive minutes, and every customer served in that stretch is satisfied. Return the largest possible
number of satisfied customers.
Examples
| Input | Output | Why |
|---|---|---|
customers = [1,0,1,2,1,1,7,5], moody = [0,1,0,1,0,1,0,1], k = 3 | 16 | Stay calm in minutes 5 to 7: 1 + 1 + 1 + 1 + 7 + 5. |
customers = [4], moody = [1], k = 1 | 4 | |
customers = [3,2,5], moody = [0,0,0], k = 2 | 10 | Nobody is unhappy anyway. |
Constraints
- 1 ≤ k ≤ n ≤ 2 × 10⁴
- 0 ≤ customers[i] ≤ 1000
- moody[i] is 0 or 1
Hints
Hint 1
Customers in calm minutes are satisfied whatever the owner does. Count them once.
Hint 2
The window only matters in moody minutes. How many extra customers does a window starting at i rescue?
Hint 3
The extra is the sum of customers[j] × moody[j] over the window: a fixed-window sum.
Where people lose marks
- Adding the calm-minute customers inside the window as well, which counts them twice.
- Sliding over all customers instead of the rescued ones.
Dry run on [1,0,1,2,1,1,7,5],[0,1,0,1,0,1,0,1],3
Read it one frame at a time, the way you would trace the code on paper in an interview. Each frame shows the state after the step it describes.
-
Step 1 / 8customers1001122314157657gain0001022304150657base10
Customers in calm minutes are satisfied whatever happens: 10. The window can only rescue the moody minutes, so slide over gain[i] = customers[i] × moody[i].
-
Step 2 / 8gain00lo0102hi2304150657base10rescued0best0
First window, minutes 0 to 2: it rescues 0.
-
Step 3 / 8gain0001lo0223hi04150657base10rescued2best2
Slide: 2 in, 0 out. This window rescues 2, the best so far.
-
Step 4 / 8gain000102lo2304hi150657base10rescued2best2
Slide: 0 in, 0 out. This window rescues 2.
-
Step 5 / 8gain00010223lo0415hi0657base10rescued3best3
Slide: 1 in, 0 out. This window rescues 3, the best so far.
-
Step 6 / 8gain0001022304lo1506hi57base10rescued1best3
Slide: 0 in, 2 out. This window rescues 1.
-
Step 7 / 8gain000102230415lo0657hibase10rescued6best6
Slide: 5 in, 0 out. This window rescues 6, the best so far.
-
Step 8 / 8answer16
Answer: 10 satisfied anyway plus the best rescue of 6, which is 16.
How to think about it
Split the answer in two. Customers served in calm minutes are satisfied whatever happens, so add them
up once. The window changes only the moody minutes it covers: it rescues customers[j] for each
moody minute j inside it. So the choice of window is the choice of the k consecutive minutes with the largest
rescued total, which is the running-sum window over customers[j] × moody[j].
The move generalises: when a window decision only changes part of the answer, separate the fixed part from the part the window controls, and slide over the second.
Complexity. Time O(n) · Space O(1)
The solution, in six languages
Each one is compiled and run against the test table before it is published. Java is reviewed by hand.
def best_calm_stretch(customers, moody, k):
base = sum(c for c, m in zip(customers, moody) if not m) # satisfied anyway
gain = [c * m for c, m in zip(customers, moody)] # what a calm minute rescues
window = sum(gain[:k])
best = window
for i in range(k, len(gain)):
window += gain[i] - gain[i - k]
best = max(best, window)
return base + best#include <vector>
#include <algorithm>
int solve(const std::vector<int>& customers, const std::vector<int>& moody, int k) {
int n = (int)customers.size(), base = 0, window = 0;
for (int i = 0; i < n; ++i) if (!moody[i]) base += customers[i]; // satisfied anyway
auto gain = [&](int i) { return customers[i] * moody[i]; }; // rescued by calm
for (int i = 0; i < k; ++i) window += gain(i);
int best = window;
for (int i = k; i < n; ++i) {
window += gain(i) - gain(i - k);
best = std::max(best, window);
}
return base + best;
}class Solution {
public int bestCalmStretch(int[] customers, int[] moody, int k) {
int n = customers.length, base = 0, window = 0;
for (int i = 0; i < n; i++) if (moody[i] == 0) base += customers[i]; // satisfied anyway
for (int i = 0; i < k; i++) window += customers[i] * moody[i];
int best = window;
for (int i = k; i < n; i++) {
window += customers[i] * moody[i] - customers[i - k] * moody[i - k];
best = Math.max(best, window);
}
return base + best;
}
}function bestCalmStretch(customers, moody, k) {
let base = 0, window = 0, best = 0;
for (let i = 0; i < customers.length; i++) if (!moody[i]) base += customers[i]; // satisfied anyway
const gain = i => customers[i] * moody[i]; // rescued by calm
for (let i = 0; i < k; i++) window += gain(i);
best = window;
for (let i = k; i < customers.length; i++) {
window += gain(i) - gain(i - k);
best = Math.max(best, window);
}
return base + best;
}fn solve(customers: &[i64], moody: &[i64], k: usize) -> i64 {
let base: i64 = customers.iter().zip(moody).filter(|(_, &m)| m == 0).map(|(&c, _)| c).sum();
let gain: Vec<i64> = customers.iter().zip(moody).map(|(&c, &m)| c * m).collect();
let mut window: i64 = gain[..k].iter().sum();
let mut best = window;
for i in k..gain.len() {
window += gain[i] - gain[i - k];
best = best.max(window);
}
base + best
}-- Satisfied anyway, plus the best fixed-width window over what calm minutes rescue.
solve :: [Int] -> [Int] -> Int -> Int
solve cs ms k = base + maximum (scanl step first (zip (drop k gain) gain))
where
base = sum [c | (c, m) <- zip cs ms, m == 0]
gain = zipWith (*) cs ms
first = sum (take k gain)
step w (new, old) = w + new - old
Variants to try
- Two separate calm stretches: keep the best window ending before each point, then combine.
- The calm stretch can be any length but costs something per minute: a maximum-subarray problem on gain minus cost.
Next problems
Best total over k consecutive days
A window of fixed width slides one place at a time: add the element that enters, subtract the one that leaves.
Open the problem → Easy10 minMost vowels in any k letters
The same fixed window as a running sum, with a count of the letters that matter as its state.
Open the problem → Medium20 minEvery place an anagram begins
Compare a window's letter counts with a pattern's in O(1) per step by tracking how many letters still differ.
Open the problem →Write a solution and run it against the real test table.
Keep going
Best total over k consecutive days
A window of fixed width slides one place at a time: add the element that enters, subtract the one that leaves.
Open the problem → Easy10 minMost vowels in any k letters
The same fixed window as a running sum, with a count of the letters that matter as its state.
Open the problem → Medium20 minEvery place an anagram begins
Compare a window's letter counts with a pattern's in O(1) per step by tracking how many letters still differ.
Open the problem → Sliding windowThe pattern behind it
A window that grows on the right, shrinks on the left, and holds an invariant at all times.
Read the pattern →Preparing for a real process? Quant interview preparation, or book a free 20-minute call.