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

  • count`.

The count in the formula represents the number of times the interval has been executed starting from an initial value of 0.

FunctioncustomClearInterval

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

  1. Use a map to store active intervals by id (object or number).
  2. In customInterval(fn, delay, period), schedule the first call with setTimeout after delay ms.
  3. After each call, increment the count and schedule the next call with delay + period * count ms.
  4. Store the timer id and a flag in the map to allow cancellation.
  5. In customClearInterval(id), clear the timer and set the flag to stop further scheduling.

Code

 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.