Overview
Standard debounce delays execution until a quiet period elapses. In real-world scenarios (scroll handlers, search-as-you-type), this can starve the callback indefinitely during sustained activity. The maxWait option guarantees the function fires at least once every maxWait milliseconds, even if calls keep arriving.
Given a stream of timestamped invocations and a configuration object, implement debounceMaxWait(events, wait, maxWait) that computes the exact timestamps at which the debounced function would fire.
Constraints
- Input events are sorted in ascending order.
waitandmaxWaitare positive integers in milliseconds.maxWait >= waitis always true.- Output timestamps must be in ascending order with no duplicates.
- Only trailing-edge fires (no leading option for this problem).
- Complexity target: $O(n)$.
Examples
// maxWait forces mid-burst fire. debounceMaxWait([0, 50, 120, 180, 250, 500], 100, 200); // → [200, 350, 600] // Events 0–180 keep resetting the debounce timer. But maxWait: 200 forces // a fire at t=200 (200ms after first call at t=0). Window resets. // Event at 250: gap from 180 is 70 < wait, but elapsed from 200 is 50 < maxWait. // Gap 250→500 exceeds wait so trailing fires at 350. Event 500 → trailing at 600.
// Natural gaps — maxWait never triggers. debounceMaxWait([0, 250, 500], 100, 300); // → [100, 350, 600] // Each event spaced > wait, so each fires trailing normally. // maxWait never kicks in because no window lasts > 300ms.
// Continuous rapid fire with periodic maxWait fires. debounceMaxWait([0, 30, 60, 90, 130, 160, 190, 220, 400], 50, 120); // → [120, 250, 450] // Continuous calls 0–220 trigger maxWait at 120 and 250. Gap to 400 > 50 so trailing at 250. // Event 400 starts new window with trailing at 450.
Notes
- The first event in a window starts both the debounce timer (
wait) and the maxWait timer. - When
maxWaitforces a fire, it closes the current window and the next event starts a new window. - A trailing edge fires at
lastEventInWindow + waitunlessmaxWaitfires first. - The fire time is always
Math.min(lastEvent + wait, windowStart + maxWait).
Solution
Reveal solution
Resources
Debounce With Max Wait
Overview
Standard debounce delays execution until a quiet period elapses. In real-world scenarios (scroll handlers, search-as-you-type), this can starve the callback indefinitely during sustained activity. The maxWait option guarantees the function fires at least once every maxWait milliseconds, even if calls keep arriving.
Given a stream of timestamped invocations and a configuration object, implement debounceMaxWait(events, wait, maxWait) that computes the exact timestamps at which the debounced function would fire.
Constraints
- Input events are sorted in ascending order.
waitandmaxWaitare positive integers in milliseconds.maxWait >= waitis always true.- Output timestamps must be in ascending order with no duplicates.
- Only trailing-edge fires (no leading option for this problem).
- Complexity target: $O(n)$.
Examples
// maxWait forces mid-burst fire. debounceMaxWait([0, 50, 120, 180, 250, 500], 100, 200); // → [200, 350, 600] // Events 0–180 keep resetting the debounce timer. But maxWait: 200 forces // a fire at t=200 (200ms after first call at t=0). Window resets. // Event at 250: gap from 180 is 70 < wait, but elapsed from 200 is 50 < maxWait. // Gap 250→500 exceeds wait so trailing fires at 350. Event 500 → trailing at 600.
// Natural gaps — maxWait never triggers. debounceMaxWait([0, 250, 500], 100, 300); // → [100, 350, 600] // Each event spaced > wait, so each fires trailing normally. // maxWait never kicks in because no window lasts > 300ms.
// Continuous rapid fire with periodic maxWait fires. debounceMaxWait([0, 30, 60, 90, 130, 160, 190, 220, 400], 50, 120); // → [120, 250, 450] // Continuous calls 0–220 trigger maxWait at 120 and 250. Gap to 400 > 50 so trailing at 250. // Event 400 starts new window with trailing at 450.
Notes
- The first event in a window starts both the debounce timer (
wait) and the maxWait timer. - When
maxWaitforces a fire, it closes the current window and the next event starts a new window. - A trailing edge fires at
lastEventInWindow + waitunlessmaxWaitfires first. - The fire time is always
Math.min(lastEvent + wait, windowStart + maxWait).