Problem#
**Function **customInterval
Given a function fn
, a number delay
and a number period
, return a number
id
.
customInterval
is a function that should execute the provided function fn
at intervals based on a linear pattern defined by the formula `delay + period
The count
in the formula represents the number of times the interval has been executed starting from an initial value of 0
.
Function customClearInterval
Given the id
. id
is the returned value from the function customInterval
.
customClearInterval
should stop executing provided function fn
at intervals.
Note: The setTimeout
and setInterval
functions in Node.js return an object, not a number.
Examples#
Example 1:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Input: delay = 50 , period = 20 , cancelTime = 225
Output: [ 50 , 120 , 210 ]
Explanation:
const t = performance. now ()
const result = []
const fn = () => {
result. push ( Math. floor ( performance. now () - t))
}
const id = customInterval( fn, delay, period)
setTimeout(() => {
customClearInterval( id)
}, 225 )
50 + 20 * 0 = 50 // 50ms - 1st function call
50 + 20 * 1 = 70 // 50ms + 70ms = 120ms - 2nd function call
50 + 20 * 2 = 90 // 50ms + 70ms + 90ms = 210ms - 3rd function call
Example 2:
1
2
3
4
5
6
Input: delay = 20 , period = 20 , cancelTime = 150
Output: [ 20 , 60 , 120 ]
Explanation:
20 + 20 * 0 = 20 // 20ms - 1st function call
20 + 20 * 1 = 40 // 20ms + 40ms = 60ms - 2nd function call
20 + 20 * 2 = 60 // 20ms + 40ms + 60ms = 120ms - 3rd function call
Example 3:
1
2
3
4
5
Input: delay = 100 , period = 200 , cancelTime = 500
Output: [ 100 , 400 ]
Explanation:
100 + 200 * 0 = 100 // 100ms - 1st function call
100 + 200 * 1 = 300 // 100ms + 300ms = 400ms - 2nd function call
Constraints:
20 <= delay, period <= 250
20 <= cancelTime <= 1000
Solution#
Method 1 – Recursive setTimeout with Linear Interval#
Intuition#
The key idea is to use setTimeout
recursively to schedule the next call with a delay that increases linearly according to the formula delay + period * count
. We keep track of the timer and count, and provide a way to clear the interval using a map.
Approach#
Use a map to store active intervals by id (object or number).
In customInterval(fn, delay, period)
, schedule the first call with setTimeout
after delay
ms.
After each call, increment the count and schedule the next call with delay + period * count
ms.
Store the timer id and a flag in the map to allow cancellation.
In customClearInterval(id)
, clear the timer and set the flag to stop further scheduling.
Code#
Javascript
Typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const customIntervalMap = new Map ();
function customInterval (fn , delay , period ) {
let count = 0 ;
let active = { stopped : false };
function tick () {
if (active .stopped ) return ;
fn ();
count ++ ;
const t = setTimeout (tick , delay + period * count );
active .timer = t ;
}
const t = setTimeout (tick , delay );
active .timer = t ;
customIntervalMap .set (active , active );
return active ;
}
function customClearInterval (id ) {
if (id && id .timer ) {
clearTimeout (id .timer );
id .stopped = true ;
customIntervalMap .delete (id );
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const customIntervalMap = new Map <object , object >();
function customInterval (fn : () => void , delay : number , period : number ): object {
let count = 0 ;
const active : { stopped : boolean ; timer? : ReturnType <typeof setTimeout > } = { stopped : false };
function tick() {
if (active .stopped ) return ;
fn ();
count ++ ;
const t = setTimeout (tick , delay + period * count );
active .timer = t ;
}
const t = setTimeout (tick , delay );
active .timer = t ;
customIntervalMap .set (active , active );
return active ;
}
function customClearInterval (id : { stopped : boolean ; timer? : ReturnType <typeof setTimeout > }) {
if (id && id .timer ) {
clearTimeout (id .timer );
id .stopped = true ;
customIntervalMap .delete (id );
}
}
Complexity#
⏰ Time complexity: O(1)
per scheduling/cancel operation.
🧺 Space complexity: O(1)
per interval, for the map and timer references.