Sliding window
Use it when the question is about a contiguous stretch and asks for a best value, a count, the longest or the shortest. Signal words: consecutive, in a row, a run, a session.
the whole pattern cardfold it
Fixed window (the size k is given): build the first window of k values, then slide. Each slide adds values[right] and subtracts values[right - k].
Variable window (the size is the answer): move right on every step. While the window breaks the rule, move left. Record the answer when the window is valid.
Longest or shortest? For the longest valid window, record after the shrink loop. For the shortest window that reaches a target, record inside the shrink loop, before each value leaves.
It needs a rule that stays broken as the window grows. Non-negative values with a sum limit have this property. Negative values do not.
Cost: each value joins once and leaves at most once, so the whole pass is O(n).
In this lesson you learn to answer questions about consecutive stretches of data in one pass. You meet two shapes of the same idea: a window of fixed size that slides along, and a window that grows and shrinks.
1. Scenario: the busiest three hours#
Kestrel Stream is running a live launch day. Sofia Reyes, product manager for Kestrel Stream, sets the requirement for the launch dashboard.
Sofia ReyesProduct Manager
On-call needs the busiest three-hour stretch of each day, so they can add capacity before it starts.
Sofia ReyesProduct Manager
The dashboard refreshes every minute, so the answer must be ready within seconds.
The dashboard counts play starts every hour. Here is one short test day, in thousands of play starts: [4, 2, 7, 1, 8, 3]. Hour 0 had 4 thousand, hour 1 had 2 thousand, and so on.
A stretch means hours in a row, such as hours 2, 3 and 4. Hours 0, 2 and 4 are not a stretch, because they skip hours. Values that sit next to each other with no gaps are called contiguous.
So the task is this: find the three contiguous hours with the largest total.
Picture yourself on a train, looking out of one window. The window always shows three trees. As the train moves, one tree leaves the view on the left and one new tree enters on the right. You never recount the trees that are still in view.
That is the whole idea of this lesson. The trees in view are the window. The tree that leaves is the value you subtract. The tree that enters is the value you add.
2. Struggle: solve it by hand first#
Before you write code, solve the test day by hand. It takes two minutes, and it shows you where the work goes.
Solve it by hand: The test day by hand: every three-hour stretch. The hand-solve sheet loads in your browser.
Aanya Rao, a graduate engineer on the Platform team, works through it on the whiteboard. She writes one row for each stretch. Left and right are the first and last hour of the stretch.
Input: [4, 2, 7, 1, 8, 3], a window of 3 hours.
| Left | Right | Hours in the window | Total | Leaves | Joins |
|---|---|---|---|---|---|
| 0 | 2 | 4, 2, 7 | 13 | none | none |
| 1 | 3 | 2, 7, 1 | 10 | 4 | 1 |
| 2 | 4 | 7, 1, 8 | 16 | 2 | 8 |
| 3 | 5 | 1, 8, 3 | 12 | 7 | 3 |
The busiest stretch is hours 2 to 4, with 16 thousand play starts.
Look at the last two columns. Each new stretch loses one hour on the left and gains one hour on the right. Remember this. You will use it soon.
The first attempt#
Lucas Martin, a software engineer on the team, turns the hand method into code.
Lucas MartinSoftware EngineerThe first attempt
Let me get a correct version first. Add up each three-hour stretch and keep the largest.
def busiest_total(plays, k):
best = None
for start in range(len(plays) - k + 1):
total = 0
for i in range(start, start + k): # add up the k hours of this stretch
total += plays[i]
if best is None or total > best:
best = total
return bestThis is correct. For the test day it adds up 4 stretches of 3 hours each, which takes no time at all. The team keeps it as the reference: every faster version must give the same answers. In each practice problem, this version is the brute-force reference that checks the tests.
How much work is it in general? With n values and a window of k, there are n − k + 1 stretches. Each stretch costs k additions. That is about (n − k + 1) × k additions.
The scale check#
Kenji Sato, the site reliability engineer on call this week, asks about the real dashboard. Besides the three-hour view, it also shows the busiest full day of the month.
Kenji SatoSite Reliability EngineerThe scale check
The real dashboard keeps per-minute data for 30 days, uses a one-day window, and shows 10,000 channels.
Here is the count for that view:
- 30 days of minutes: 30 × 24 × 60 = 43,200 values per channel.
- A one-day window: k = 1,440 minutes.
- Stretches per channel: 43,200 − 1,440 + 1 = 41,761.
- Additions per channel: 41,761 × 1,440, which is about 60 million.
- Across 10,000 channels: about 6 × 10^11 additions for every refresh.
Predict the cost
Q A computer does about 10^8 simple operations a second. About how long does one refresh take with the first attempt?
Answer & explanation
Answer: C
6 × 10^11 ÷ 10^8 = 6,000 seconds, which is 100 minutes. The dashboard refreshes every minute, so the first attempt is about 100 times too slow.
The first attempt is correct, but at this size it cannot keep up. Now the team looks for the work it repeats.
3. See: neighbouring windows share almost everything#
Can we do better?#
Daniel Okafor, the staff engineer, puts two neighbouring stretches side by side.
Daniel OkaforStaff EngineerCan we do better?
Neighbouring windows share almost every minute. Can we do better?
Look at two stretches from the test day:
- Hours 0 to 2: 4 + 2 + 7 = 13.
- Hours 1 to 3: 2 + 7 + 1 = 10.
Both totals contain 2 + 7. The first attempt adds those two numbers twice. On the real dashboard, two neighbouring one-day windows share 1,439 of their 1,440 minutes.
So do not start again. Start from the old total, take away the value that leaves, and add the value that joins:
new total = old total − value that leaves + value that joins
For hours 1 to 3, that gives 13 − 4 + 1 = 10. It is the same answer. You did this in the hand trace already: the Leaves and Joins columns held everything you needed.
This method is called a sliding window. You keep a running answer for a stretch of consecutive values, and you update it as the stretch moves. One move costs two operations, whether the window holds 3 values or 1,440.
Race: First attempt against the sliding window, one-hour window (k = 60). The operation counter loads in your browser.
The race counts the operations of both versions on per-minute data with a one-hour window, k = 60. At 100,000 values, the first attempt does about 6 million additions. The sliding window does about 200,000 operations. With the dashboard's one-day window, the gap is wider still: 1,440 additions per step against 2.
Here is a new test day, [2, 1, 5, 1, 3, 2], with a window of 3. The player stops before each move and asks you to predict the new total.
Dry run: Predict each slide of a three-hour window. The step-by-step player loads in your browser.
Reading without the player? Cover the Total column and predict it row by row.
| Left | Right | Leaves | Joins | Total | Best |
|---|---|---|---|---|---|
| 0 | 2 | none | none | 2 + 1 + 5 = 8 | 8 |
| 1 | 3 | 2 | 1 | 8 − 2 + 1 = 7 | 8 |
| 2 | 4 | 1 | 3 | 7 − 1 + 3 = 9 | 9 |
| 3 | 5 | 5 | 2 | 9 − 5 + 2 = 6 | 9 |
When right moves to index 4, the value 1 leaves and the value 3 joins: 7 − 1 + 3 = 9. The best total is 9.
When the size is not given#
Sometimes the question does not fix the size of the window. Kestrel Stream has a bandwidth budget, for example. What is the longest stretch of hours whose total stays within 9? Now the size of the window is the answer.
The rule for this is short. The right edge always moves forward, one value at a time. The left edge moves forward only while the window breaks the rule.
A window that grows and shrinks like this is called a variable window. A window of one set size is a fixed window.
Same values, [2, 1, 5, 1, 3, 2]. Find the longest stretch with a total of at most 9.
Dry run: Longest stretch with a total of at most 9. The step-by-step player loads in your browser.
| Right | Joins | Total after joining | Leaves while over 9 | Window | Length | Best |
|---|---|---|---|---|---|---|
| 0 | 2 | 2 | none | 2 | 1 | 1 |
| 1 | 1 | 3 | none | 2, 1 | 2 | 2 |
| 2 | 5 | 8 | none | 2, 1, 5 | 3 | 3 |
| 3 | 1 | 9 | none | 2, 1, 5, 1 | 4 | 4 |
| 4 | 3 | 12 | 2, then 1 (total 10, then 9) | 5, 1, 3 | 3 | 4 |
| 5 | 2 | 11 | 5 (total 6) | 1, 3, 2 | 3 | 4 |
At right = 4, the total is 12. Removing one value is not enough, because 10 is still over 9. The left edge keeps moving until the window fits again. The longest stretch is 4 hours: [2, 1, 5, 1].
4. Shape: the pattern#
Daniel names the rule that keeps both versions correct. This rule is the window invariant, and every line of the templates below exists to protect it.
The window always holds exactly the values from left to right, and its running total always equals their sum.
Every step does one of two things. It moves right and adds the new value, or it moves left and subtracts the old one. Do both parts of a move together, and the invariant cannot break.
Why can moving left never skip a better answer? In these problems the values are never negative. If a window is over the budget, every longer window with the same left edge is over the budget too. So once the left value has to leave, no later window can use it.
Use it when the question is about a contiguous stretch and asks for a best value, a count, the longest or the shortest. Signal words: consecutive, in a row, a run, a session.
Fixed window (the size k is given): build the first window of k values, then slide. Each slide adds values[right] and subtracts values[right - k].
Variable window (the size is the answer): move right on every step. While the window breaks the rule, move left. Record the answer when the window is valid.
Longest or shortest? For the longest valid window, record after the shrink loop. For the shortest window that reaches a target, record inside the shrink loop, before each value leaves.
It needs a rule that stays broken as the window grows. Non-negative values with a sum limit have this property. Negative values do not.
Cost: each value joins once and leaves at most once, so the whole pass is O(n).
Template 1: a fixed window#
The template assumes 1 ≤ k ≤ n. The edge case where k is larger than n comes in Stretch.
def best_window_sum(values, k):
# [1] Build the first window: the first k values.
window = 0
for i in range(k):
window += values[i]
best = window
# [2] Slide: the value at right joins, the value at right - k leaves.
for right in range(k, len(values)):
window += values[right] - values[right - k]
# [3] Keep the best total seen so far.
best = max(best, window)
return bestpublic long bestWindowSum(int[] values, int k) {
// [1] Build the first window: the first k values.
long window = 0; // 64-bit, because totals can pass 2^31
for (int i = 0; i < k; i++) {
window += values[i];
}
long best = window;
// [2] Slide: the value at right joins, the value at right - k leaves.
for (int right = k; right < values.length; right++) {
window += values[right] - values[right - k];
// [3] Keep the best total seen so far.
best = Math.max(best, window);
}
return best;
}long long bestWindowSum(const vector<int>& values, int k) {
// [1] Build the first window: the first k values.
long long window = 0; // 64-bit, because totals can pass 2^31
for (int i = 0; i < k; i++) {
window += values[i];
}
long long best = window;
// [2] Slide: the value at right joins, the value at right - k leaves.
for (int right = k; right < (int) values.size(); right++) {
window += values[right] - values[right - k];
// [3] Keep the best total seen so far.
best = max(best, window);
}
return best;
}function bestWindowSum(values, k) {
// [1] Build the first window: the first k values.
let window = 0;
for (let i = 0; i < k; i++) {
window += values[i];
}
let best = window;
// [2] Slide: the value at right joins, the value at right - k leaves.
for (let right = k; right < values.length; right++) {
window += values[right] - values[right - k];
// [3] Keep the best total seen so far.
best = Math.max(best, window);
}
return best;
}Template 2: a variable window, longest#
def longest_within_budget(values, budget):
left = 0
window = 0
best = 0
for right in range(len(values)):
# [1] The value at right joins the window.
window += values[right]
# [2] While the window breaks the rule, the value at left leaves.
while window > budget:
window -= values[left]
left += 1
# [3] The window is valid again: record its length.
best = max(best, right - left + 1)
return bestpublic int longestWithinBudget(int[] values, int budget) {
int left = 0;
long window = 0;
int best = 0;
for (int right = 0; right < values.length; right++) {
// [1] The value at right joins the window.
window += values[right];
// [2] While the window breaks the rule, the value at left leaves.
while (window > budget) {
window -= values[left];
left++;
}
// [3] The window is valid again: record its length.
best = Math.max(best, right - left + 1);
}
return best;
}int longestWithinBudget(const vector<int>& values, int budget) {
int left = 0;
long long window = 0;
int best = 0;
for (int right = 0; right < (int) values.size(); right++) {
// [1] The value at right joins the window.
window += values[right];
// [2] While the window breaks the rule, the value at left leaves.
while (window > budget) {
window -= values[left];
left++;
}
// [3] The window is valid again: record its length.
best = max(best, right - left + 1);
}
return best;
}function longestWithinBudget(values, budget) {
let left = 0;
let window = 0;
let best = 0;
for (let right = 0; right < values.length; right++) {
// [1] The value at right joins the window.
window += values[right];
// [2] While the window breaks the rule, the value at left leaves.
while (window > budget) {
window -= values[left];
left++;
}
// [3] The window is valid again: record its length.
best = Math.max(best, right - left + 1);
}
return best;
}Rebuild the template: put its lines back in order. Loads in your browser.
Template 3: a variable window, shortest#
The shortest version moves the record inside the loop. While the window still reaches the target, it is a candidate, so you record it and then try a smaller one.
def shortest_reaching_target(values, target):
n = len(values)
left = 0
window = 0
best = n + 1
for right in range(n):
# [1] The value at right joins the window.
window += values[right]
# [2] While the window still reaches the target, record it, then the value at left leaves.
while window >= target:
best = min(best, right - left + 1)
window -= values[left]
left += 1
# [3] If no window reached the target, report 0.
return best if best <= n else 0public int shortestReachingTarget(int[] values, long target) {
int n = values.length;
int left = 0;
long window = 0;
int best = n + 1;
for (int right = 0; right < n; right++) {
// [1] The value at right joins the window.
window += values[right];
// [2] While the window still reaches the target, record it, then the value at left leaves.
while (window >= target) {
best = Math.min(best, right - left + 1);
window -= values[left];
left++;
}
}
// [3] If no window reached the target, report 0.
return best <= n ? best : 0;
}int shortestReachingTarget(const vector<int>& values, long long target) {
int n = values.size();
int left = 0;
long long window = 0;
int best = n + 1;
for (int right = 0; right < n; right++) {
// [1] The value at right joins the window.
window += values[right];
// [2] While the window still reaches the target, record it, then the value at left leaves.
while (window >= target) {
best = min(best, right - left + 1);
window -= values[left];
left++;
}
}
// [3] If no window reached the target, report 0.
return best <= n ? best : 0;
}function shortestReachingTarget(values, target) {
const n = values.length;
let left = 0;
let window = 0;
let best = n + 1;
for (let right = 0; right < n; right++) {
// [1] The value at right joins the window.
window += values[right];
// [2] While the window still reaches the target, record it, then the value at left leaves.
while (window >= target) {
best = Math.min(best, right - left + 1);
window -= values[left];
left++;
}
}
// [3] If no window reached the target, report 0.
return best <= n ? best : 0;
}Kestrel Observe stores log data by the hour. The storage team asks for the longest run of hours in which ingestion stays at or under 500 units. The hourly ingestion is [100, 200, 300, 50, 50, 400].
This is Template 2 with budget = 500.
| Right | Joins | Total after joining | Leaves while over 500 | Window | Best |
|---|---|---|---|---|---|
| 0 | 100 | 100 | none | 100 | 1 |
| 1 | 200 | 300 | none | 100, 200 | 2 |
| 2 | 300 | 600 | 100 (total 500) | 200, 300 | 2 |
| 3 | 50 | 550 | 200 (total 350) | 300, 50 | 2 |
| 4 | 50 | 400 | none | 300, 50, 50 | 3 |
| 5 | 400 | 800 | 300 (total 500) | 50, 50, 400 | 3 |
The answer is 3 hours. Look at right = 2: a total of exactly 500 is allowed, because the rule says "at or under". The while condition is window > budget, not window >= budget.
Complexity in plain words#
- Fixed window. Building the first window takes k additions. Each slide takes two operations. That is about n operations in all, so the time is O(n).
- Variable window. Right moves n times. Left also moves at most n times in total, across all the while loops together. So the loop inside a loop looks like O(n^2), but the total work is O(n).
- Amortised cost. Some steps of the inner loop do a lot of work and most do none, but the total stays small. Counting the cost across the whole run like this is called amortised cost (Module 1).
- Space. A few variables, so O(1) extra memory. Some practice problems keep a hash map inside the window; then the space grows with the number of different values in it.
- At dashboard size. About 43,200 steps per channel, two operations each. Across 10,000 channels that is under 10^9 operations: about 9 seconds on one core, instead of 100 minutes. That fits inside the one-minute refresh, and channels can also run in parallel.
5. Stretch: edges, mistakes and variations#
Edge cases#
Kenji brings the edge cases he has seen in production.
A new channel has only 2 hours of data, [3, 9], and the window is 3 hours. There is no full window at all.
Agree on a sentinel with the caller: a special return value that means "no answer". Play counts are never negative, so -1 is safe here, because it can never be a real total. Check for this before you build the first window.
With k = 1, every window is one value, so the answer is the largest value: for [2, 9, 4] it is 9. With k = n, there is exactly one window, the whole array: for [2, 9, 4] and k = 3 it is 15. Check that your code handles both. When k = n, the slide loop runs zero times.
Kestrel Pay reports net revenue per hour, and refunds make some hours negative: [-3, -1, -4, -2] with k = 2. The window totals are -4, -5 and -6, so the best is -4.
A fixed window still works with negative values, because its size never depends on the values. Start the best from the first window's total, not from 0. Starting from 0 would wrongly report 0.
Find the longest run within an ingestion budget of 500 for [600, 700]. Every single hour is already over the budget, so the left edge passes the right edge and the window is empty.
Its length, right − left + 1, is 0, so the answer is 0. Make sure your code returns 0 here and does not read outside the array.
The mistake museum#
Kestrel Pay wants the shortest stretch of hours with a net total of at least 167. Refunds make some hours negative.
Counterexample: [84, -37, 32, 40, 95], target 167. Template 3 returns 5. The correct answer is 3: the hours [32, 40, 95] total exactly 167.
What went wrong? The full window totals 214, so the template records length 5 and removes 84. The total drops to 130, below the target, so it stops shrinking. It never tries removing -37 as well, which would raise the total again.
With negative values, removing a value can increase the total, so shrinking is no longer safe. The right tool is prefix sums with a monotonic deque (LeetCode 862: Shortest Subarray with Sum at Least K), taught in Product Districts.
This shortest-window code shrinks with if instead of while:
if window >= target: # bug: this must be a while loop
best = min(best, right - left + 1)
window -= values[left]
left += 1Counterexample: [1, 1, 1, 7], target 7. When 7 joins, the window [1, 1, 1, 7] totals 10. The if records length 4, removes one value, and moves on.
The window never shrinks to [7]. The bug returns 4; the correct answer is 1.
One new value can make several old values unnecessary, so one shrink per step is not enough. Use while.
A subtle point: in a longest-window problem, an if still gives the right length. The window never shrinks; it slides along at the best size found so far.
But that window can hold an invalid stretch in between, which makes the code hard to reason about. Use while in both.
When the pattern does not apply#
Sofia brings a different question from the content team: which three hours had the most play starts, even if they are not next to each other? For [4, 2, 7, 1, 8, 3], the answer is hours 4, 2 and 0, with 8, 7 and 4 thousand.
There is no stretch here, so there is no window to slide. Sort the hours by play starts and take the top three, or keep the three largest values in one pass.
The signal to look for is "consecutive". Without it, a sliding window is the wrong tool.
Product variations#
Sofia brings three product changes. Each one keeps the window but changes what the window tracks.
Kestrel Stream tags every play with a content category, such as music, podcast or audiobook. The recommendations team wants the longest run of plays that touches at most two categories. For the plays music, music, podcast, music, audiobook, the answer is 4.
The window still grows on the right and shrinks on the left. Its state is now a count of plays per category, kept in a hash map. Shrink while the map holds more than two categories.
To count runs with exactly K categories, use count(at most K) − count(at most K − 1). You build this in the At most K concept.
Kestrel Freight scans parcel codes on a conveyor. A batch of k parcels was loaded in some order, and the team wants to know where the batch passed the scanner. For the batch A, B, C and the stream D, C, A, B, E, the window at positions 1 to 3 holds C, A, B: a match.
This is a fixed window of size k plus a count of each code. Slide the window and compare its counts with the batch's counts. You build this in the Windows with counts concept.
The live-events team wants the peak number of viewers in every 10-minute window, not the total. A running total cannot do this. When the largest value leaves, you cannot subtract your way to the new maximum. For [3, 1, 4, 1, 5] with windows of 3, the peaks are 4, 4 and 5.
The tool is a monotonic deque: a queue kept in decreasing order, so the maximum of the window is always at the front. It is a preview of Product Districts (LeetCode 239: Sliding Window Maximum).
Game: window rider. Coming to the map as a side path.
Why this matters in real systems#
6. Say: lock it in#
Explain it back#
Explain it back: write the idea in your own words and get feedback.
In two or three sentences, explain to a teammate why the sliding window is O(n), and when it stops working. The AI tutor checks your answer against the invariant and the key points of this lesson.
Here is how Aanya explains it, now that she has built it.
Aanya RaoGraduate Engineer, Platform
I keep a running total. Each move adds the value that joins and subtracts the value that leaves: two operations per step.
Aanya RaoGraduate Engineer, Platform
For a variable window, right always moves forward and left moves only while the rule is broken. Each value joins once and leaves once.
Aanya RaoGraduate Engineer, Platform
It breaks when values can be negative, because removing a value can then raise the total.
The 60-second interview answer#
This question is about consecutive values, so I would use a sliding window. The first attempt recomputes every window, which costs about n times k additions. At these sizes, that is too slow.
Instead, I keep a running total for the window. When the window moves, I add the value that joins and subtract the value that leaves. Each step is constant time, so the whole pass is O(n) with O(1) extra space.
If the size is not fixed, I grow the window on the right and shrink it from the left while it breaks the rule. That is still O(n), because each value enters once and leaves once. It needs non-negative values for a sum rule; with negative values I would switch to prefix sums.
I would test k larger than n, k equal to 1 and to n, and inputs with no valid window.
Checkpoint#
Checkpoint · Spot the pattern
Q1/4 Which request is a sliding-window problem?
Answer & explanation
Answer: B
"Consecutive minutes" is the signal: the answer is a contiguous stretch. The others do not ask about a stretch of neighbouring values.
Q2/4 A fixed window of 4 values totals 30. The value 6 leaves and the value 9 joins. What is the new total?
Answer & explanation
Answer: B
New total = old total − value that leaves + value that joins = 30 − 6 + 9 = 33. Forgetting to subtract gives 39.
Q3/4 An array has 10 values. How many different windows of size 4 does it have?
Answer & explanation
Answer: C
There are n − k + 1 windows: 10 − 4 + 1 = 7. They start at indexes 0 to 6.
Q4/4 The first attempt re-adds every window. About how many additions does it do for n = 100,000 and k = 1,000?
Answer & explanation
Answer: C
(n − k + 1) × k = 99,001 × 1,000, which is about 10^8. The sliding window needs about 2 × 10^5 operations for the same input.
Checkpoint · Variable windows
Q1/3 In a shortest-window solution, why must the shrink step be a while loop and not an if?
Answer & explanation
Answer: B
With
[1, 1, 1, 7]and target 7, the window must drop all three 1s once 7 joins. An if removes only one per step and returns 4 instead of 1.Q2/3 Where do you record the answer in a longest-valid-window solution?
Answer & explanation
Answer: C
Longest: record after shrinking, when the window is valid. Shortest windows that reach a target are the opposite: record inside the shrink loop.
Q3/3 A shrinking window finds the shortest stretch with a total of at least 167 in
[84, -37, 32, 40, 95]. It returns 5, but the answer is 3. Why?Answer & explanation
Answer: B
After removing 84 the total drops below the target, so the shrink stops. Removing −37 next would raise it again. Negative values break the shrinking rule; prefix sums with a monotonic deque solve it.
Checkpoint · Edges and limits
Q1/3 A dashboard asks for the busiest 3-hour window, but a new channel has only 2 hours of data. What should the code do?
Answer & explanation
Answer: C
There is no full window, so there is no real answer. Play counts are never negative, so -1 is a safe sentinel. 0 could be a real total for a silent channel.
Q2/3 Which question should NOT be solved with a sliding window?
Answer & explanation
Answer: A
Without "consecutive" there is no stretch to slide. Sort the hours, or keep the three largest values in one pass.
Q3/3 Which statement is the window invariant?
Answer & explanation
Answer: C
The invariant holds for fixed and variable windows alike. Each move changes an edge and the total together, so the total always matches the window.
Ten questions on this lesson. Pass with 80% or more to open the gate to the next stretch on the Academy map.
Practice ladder#
| Step | Problem | Product line | Level | What it practises |
|---|---|---|---|---|
| 1 | Busiest stretch on the launch dashboard | Stream | Easy | Fixed window, earliest tie, 64-bit totals |
| 2 | Error bursts on the status page | Observe | Easy | Fixed window, counting windows |
| 3 | Longest delivery run in one shift | Freight | Medium | Variable window, longest |
| 4 | Longest fresh listening session | Stream | Medium | Variable window with a last-seen map |
| 5 | Fewest hours to a revenue target | Pay | Medium | Variable window, shortest |
Review cards#
Review cards from this lesson.
Five cards from this lesson join your spaced-review deck. The first one comes back tomorrow.