2725. 间隔取消
2725. 间隔取消
题目
Given a function fn, an array of arguments args, and an interval time t, return a cancel function cancelFn.
After a delay of cancelTimeMs, the returned cancel function cancelFn will be invoked.
setTimeout(cancelFn, cancelTimeMs)
The function fn should be called with args immediately and then called again every t milliseconds until cancelFn is called at cancelTimeMs ms.
Example 1:
Input: fn = (x) => x * 2, args = [4], t = 35
Output:
[
{"time": 0, "returned": 8},
{"time": 35, "returned": 8},
{"time": 70, "returned": 8},
{"time": 105, "returned": 8},
{"time": 140, "returned": 8},
]
Explanation:
const cancelTimeMs = 190;
const cancelFn = cancellable((x) => x * 2, [4], 35);
setTimeout(cancelFn, cancelTimeMs);
Every 35ms, fn(4) is called. Until t=190ms, then it is cancelled.
1st fn call is at 0ms. fn(4) returns 8.
2nd fn call is at 35ms. fn(4) returns 8.
3rd fn call is at 70ms. fn(4) returns 8.
4th fn call is at 105ms. fn(4) returns 8.
5th fn call is at 140ms. fn(4) returns 8.
6th fn call is at 175ms. fn(4) returns 8.
Cancelled at 190ms
Example 2:
Input: fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 30
Output:
[
{"time": 0, "returned": 10},
{"time": 30, "returned": 10},
{"time": 60, "returned": 10},
{"time": 90, "returned": 10},
{"time": 120, "returned": 10},
]
Explanation:
const cancelTimeMs = 165;
const cancelFn = cancellable((x1, x2) => (x1 * x2), [2, 5], 30)
setTimeout(cancelFn, cancelTimeMs)
Every 30ms, fn(2, 5) is called. Until t=165ms, then it is cancelled.
1st fn call is at 0ms
2nd fn call is at 30ms
3rd fn call is at 60ms
4th fn call is at 90ms
5th fn call is at 120ms
6th fn call is at 150ms
Cancelled at 165ms
Example 3:
Input: fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50
Output:
[
{"time": 0, "returned": 9},
{"time": 50, "returned": 9},
{"time": 100, "returned": 9},
]
Explanation:
const cancelTimeMs = 180;
const cancelFn = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50)
setTimeout(cancelFn, cancelTimeMs)
Every 50ms, fn(5, 1, 3) is called. Until t=180ms, then it is cancelled.
1st fn call is at 0ms
2nd fn call is at 50ms
3rd fn call is at 100ms
4th fn call is at 150ms
Cancelled at 180ms
Constraints:
fnis a functionargsis a valid JSON array1 <= args.length <= 1030 <= t <= 10010 <= cancelTimeMs <= 500
题目大意
现给定一个函数 fn,一个参数数组 args 和一个时间间隔 t,返回一个取消函数 cancelFn。
在经过 cancelTimeMs 毫秒的延迟后,将调用返回的取消函数 cancelFn。
setTimeout(cancelFn, cancelTimeMs)
函数 fn 应立即使用参数 args 调用,然后每隔 t 毫秒调用一次,直到在 cancelTimeMs 毫秒时调用 cancelFn。
提示:
fn是一个函数args是一个有效的 JSON 数组1 <= args.length <= 1030 <= t <= 10010 <= cancelT <= 500
解题思路
- 题目要求函数
fn应立即使用参数args调用,然后每隔t毫秒调用一次,所以立即手动执行fn一次。 - 使用
setInterval来启动定时器,每隔delay毫秒会执行一次传入的函数fn,第一次执行发生在delay毫秒之后。 setInterval返回一个intervalId,这是唯一标识这个定时器的值,可以通过调用clearInterval(intervalId)来取消定时器。- 返回取消函数,这个取消函数在被调用时,会停止定时器的继续执行。
复杂度分析
- 时间复杂度:
O(1),因为setInterval和clearInterval都是常数时间操作。 - 空间复杂度:
O(1),只存储了intervalId作为唯一的定时器标识。
代码
/**
* @param {Function} fn
* @param {Array} args
* @param {number} t
* @return {Function}
*/
var cancellable = function (fn, args, t) {
// 立即调用一次 fn
fn(...args);
// 使用 setInterval 启动定时器,每隔 t 毫秒执行一次 fn
const intervalId = setInterval(() => fn(...args), t);
// 返回一个取消函数,可以通过调用该函数来清除定时器
const cancelFn = () => clearInterval(intervalId);
return cancelFn;
};
/**
* const result = [];
*
* const fn = (x) => x * 2;
* const args = [4], t = 35, cancelTimeMs = 190;
*
* const start = performance.now();
*
* const log = (...argsArr) => {
* const diff = Math.floor(performance.now() - start);
* result.push({"time": diff, "returned": fn(...argsArr)});
* }
*
* const cancel = cancellable(log, args, t);
*
* setTimeout(cancel, cancelTimeMs);
*
* setTimeout(() => {
* console.log(result);
* // [
* // {"time":0,"returned":8},
* // {"time":35,"returned":8},
* // {"time":70,"returned":8},
* // {"time":105,"returned":8},
* // {"time":140,"returned":8},
* // {"time":175,"returned":8}
* // ]
* }, cancelTimeMs + t + 15)
*/
