说在前面
🎈不知道大家对于算法的学习是一个怎样的心态呢?为了面试还是因为兴趣?不管是出于什么原因,算法学习需要持续保持。
题目描述
现给定一个函数 fn,一个参数数组 args 和一个时间间隔 t,返回一个取消函数 cancelFn。
在经过 cancelTimeMs 毫秒的延迟后,将调用返回的取消函数 cancelFn。
setTimeout(cancelFn, cancelTimeMs)
函数 fn 应立即使用参数 args 调用,然后每隔 t 毫秒调用一次,直到在 cancelTimeMs 毫秒时调用 cancelFn。
示例 1:
输入:fn = (x) => x * 2, args = [4], t = 35, cancelT = 190 输出: [ {"time": 0, "returned": 8}, {"time": 35, "returned": 8}, {"time": 70, "returned": 8}, {"time": 105, "returned": 8}, {"time": 140, "returned": 8}, {"time": 175, "returned": 8} ] 解释: const cancelTimeMs = 190; const cancelFn = cancellable((x) => x * 2, [4], 35); setTimeout(cancelFn, cancelTimeMs); 每隔 35ms,调用 fn(4)。直到 t=190ms,然后取消。 第一次调用 fn 是在 0ms。fn(4) 返回 8。 第二次调用 fn 是在 35ms。fn(4) 返回 8。 第三次调用 fn 是在 70ms。fn(4) 返回 8。 第四次调用 fn 是在 105ms。fn(4) 返回 8。 第五次调用 fn 是在 140ms。fn(4) 返回 8。 第六次调用 fn 是在 175ms。fn(4) 返回 8。 在 t=190ms 时取消
示例 2:
输入:fn = (x1, x2) => (x1 * x2), args = [2, 5], t = 30, cancelT = 165 输出: [ {"time": 0, "returned": 10}, {"time": 30, "returned": 10}, {"time": 60, "returned": 10}, {"time": 90, "returned": 10}, {"time": 120, "returned": 10}, {"time": 150, "returned": 10} ] 解释: const cancelTimeMs = 165; const cancelFn = cancellable((x1, x2) => (x1 * x2), [2, 5], 30) setTimeout(cancelFn, cancelTimeMs) 每隔 30ms,调用 fn(2, 5)。直到 t=165ms,然后取消。 第一次调用 fn 是在 0ms 第二次调用 fn 是在 30ms 第三次调用 fn 是在 60ms 第四次调用 fn 是在 90ms 第五次调用 fn 是在 120ms 第六次调用 fn 是在 150ms 在 165ms 取消
示例 3:
输入:fn = (x1, x2, x3) => (x1 + x2 + x3), args = [5, 1, 3], t = 50, cancelT = 180 输出: [ {"time": 0, "returned": 9}, {"time": 50, "returned": 9}, {"time": 100, "returned": 9}, {"time": 150, "returned": 9} ] 解释: const cancelTimeMs = 180; const cancelFn = cancellable((x1, x2, x3) => (x1 + x2 + x3), [5, 1, 3], 50) setTimeout(cancelFn, cancelTimeMs) 每隔 50ms,调用 fn(5, 1, 3)。直到 t=180ms,然后取消。 第一次调用 fn 是在 0ms 第二次调用 fn 是在 50ms 第三次调用 fn 是在 100ms 第四次调用 fn 是在 150ms 在 180ms 取消
提示:
- fn 是一个函数
- args 是一个有效的 JSON 数组
- 1 <= args.length <= 10
- 30 <= t <= 100
- 10 <= cancelT <= 500
解题思路
- 1、调用 fn 函数并传入参数数组 args,以初始化结果。
- 2、使用 setInterval 创建定时器,并在每次触发时调用 fn 函数并传入参数数组 args。
- 3、返回一个无参数的函数,用于清除定时器。
- 4、在外部使用返回的函数即可取消定时器。
实际使用示例中,代码定义了一个辅助函数 log,用于记录每次执行 fn 函数的返回值,并添加时间戳记录。然后使用 cancellable 函数将 log 函数包裹起来,创建一个可取消的定时任务。在定时任务结束后,输出记录结果。
AC代码
/** * @param {Function} fn * @param {Array} args * @param {number} t * @return {Function} */ var cancellable = function(fn, args, t) { fn(...args); const timer = setInterval(()=>{ fn(...args); },t); return ()=>{clearInterval(timer)}; }; /** * 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) */
公众号
关注公众号『前端也能这么有趣
』,获取更多有趣内容。
说在后面
🎉 这里是 JYeontu,现在是一名前端工程师,有空会刷刷算法题,平时喜欢打羽毛球 🏸 ,平时也喜欢写些东西,既为自己记录 📋,也希望可以对大家有那么一丢丢的帮助,写的不好望多多谅解 🙇,写错的地方望指出,定会认真改进 😊,偶尔也会在自己的公众号『
前端也能这么有趣
』发一些比较有趣的文章,有兴趣的也可以关注下。在此谢谢大家的支持,我们下文再见 🙌。