跳至主要內容

2666. 只允许一次函数调用


2666. 只允许一次函数调用

🟢   🔗 力扣open in new window LeetCodeopen in new window

题目

Given a function fn, return a new function that is identical to the original function except that it ensures fn is called at most once.

  • The first time the returned function is called, it should return the same result as fn.
  • Every subsequent time it is called, it should return undefined.

Example 1:

Input: fn = (a,b,c) => (a + b + c), calls = [[1,2,3],[2,3,6]]

Output: [{"calls":1,"value":6}]

Explanation:

const onceFn = once(fn);

onceFn(1, 2, 3); // 6

onceFn(2, 3, 6); // undefined, fn was not called

Example 2:

Input: fn = (a,b,c) => (a * b * c), calls = [[5,7,4],[2,3,6],[4,6,8]]

Output: [{"calls":1,"value":140}]

Explanation:

const onceFn = once(fn);

onceFn(5, 7, 4); // 140

onceFn(2, 3, 6); // undefined, fn was not called

onceFn(4, 6, 8); // undefined, fn was not called

Constraints:

  • calls is a valid JSON array
  • 1 <= calls.length <= 10
  • 1 <= calls[i].length <= 100
  • 2 <= JSON.stringify(calls).length <= 1000

题目大意

给定一个函数 fn ,它返回一个新的函数,返回的函数与原始函数完全相同,只不过它确保 fn 最多被调用一次。

  • 第一次调用返回的函数时,它应该返回与 fn 相同的结果。
  • 第一次后的每次调用,它应该返回 undefined

提示:

  • calls 是一个有效的 JSON 数组
  • 1 <= calls.length <= 10
  • 1 <= calls[i].length <= 100
  • 2 <= JSON.stringify(calls).length <= 1000

解题思路

这道题的核心在于“函数只能被调用一次”的机制,这个设计模式非常适合一些需要控制函数调用次数的场景,比如防止多次执行某个动作。

可以利用闭包来实现,闭包使得我们能够在返回的函数中保持对原始函数调用状态的追踪,从而控制它只能被调用一次。

  1. 使用一个标志called 来跟踪该函数是否已经被调用过,初始为 false
  2. 返回的匿名函数,每次调用时会检查 called 是否为 true。如果为 false,则调用 fn,否则返回 undefined

复杂度分析

  • 时间复杂度O(1),每次调用时只检查标志变量并做出相应操作。
  • 空间复杂度O(1),只存储一个布尔变量来跟踪调用状态。

代码

/**
 * @param {Function} fn
 * @return {Function}
 */
var once = function (fn) {
	let called = false; // 用于跟踪函数是否已被调用
	return function (...args) {
		if (!called) {
			called = true; // 第一次调用时,标记为已调用
			return fn(...args); // 调用传入的函数,并传递参数
		}
		return undefined; // 如果已被调用,返回 undefined
	};
};

/**
 * let fn = (a,b,c) => (a + b + c)
 * let onceFn = once(fn)
 *
 * onceFn(1,2,3); // 6
 * onceFn(2,3,6); // returns undefined without calling fn
 */