Leetcode JavaScript 问题2025年4月19日 | 阅读 15 分钟 引言编码面试和算法竞赛的领域充满了需要你全力以赴的问题。LeetCode 绝对是一个开发者磨练技术能力和解决问题技巧的重要平台。在 LeetCode 上,一个庞大的开发者群体可以找到从最简单到最复杂的各种编码任务。它就像一个熔炉,可以让你锻造算法技能并学习如何使用数据结构。 在众多可用的编程语言中,选择一种具有广泛采用且在 Web 开发过程中很常见的灵活语言。本文致力于 LeetCode JavaScript 问题选集,为中级或高级开发人员提供解决问题技巧发展的有用技术、策略和资源。 无论您是希望成为算法问题大师的资深 JavaScript 程序员,还是只是一个刚开始踏上 LeetCode 平台解决问题之旅的新手,本指南都旨在为您提供成功所需的知识和技能。利用 JavaScript 的力量,我们将踏上揭示代码难题为何如此棘手的旅程,并逐一揭开算法的奥秘,走向万维网。 理解 LeetCode 问题最起码的步骤之一是彻底了解 LeetCode 问题本身。在这里,这些问题旨在多方面地挑战您的编码技能,例如算法效率、数据结构操作和问题分析。每个问题通常都有一个定义、限制和示例,以演示预期的输入-输出。在尝试解决这些问题之前,您应该花足够的时间来理解它们。 成功策略
学习和练习资源
问题 1给定一个整数 n,如果 n 是 2 的幂,则返回 true;否则,返回 false。 如果存在整数 x,使得 n == 2^x,则整数 n 是 2 的幂。 示例 1 输入: n = 1 输出: true 解释: 2^0 = 1 示例 2 输入: n = 16 输出: true 解释: 2^4 = 16 示例 3 输入: n = 3 输出: false 约束 -231 <= n <= 231 - 1 JavaScript 此过程通过检查 n 是否只有一个位设置为 1 来工作。如果 n 是 2 的幂,则只有第一个位会设置,而在第一个位设置为 1 之后,其余位都会翻转。因此,n & n-1 将为 2 的幂产生零的按位 AND 值。 问题 2 给定一个正整数 millis,编写一个异步函数,使其睡眠 millis 毫秒。它可以解析任何值。 示例 1 输入: millis = 100 输出: 100 解释: 应返回一个在 100ms 后解析的 promise。 let t = Date.now(); sleep(100).then(() => { console.log(Date.now() - t); // 100 }); 示例 2 输入: millis = 200 输出: 200 解释: 应返回一个在 200ms 后解析的 promise。 约束 1 <= millis <= 1000 JavaScript 输出 Output: 100 Elapsed time: 100 Output: 200 Elapsed time: 200 此代码返回一个 Promise,该 Promise 在指示的毫秒延迟后解析。然后,将设计一种方法来处理 promise 的已完成值——在我们的例子中,它就是 millis 参数本身。 问题 3 给定一个整数数组 nums,一个 reducer 函数 fn,以及一个初始值 init,通过按顺序将前一个计算的返回值传递给 fn 函数来计算数组中的每个元素,并返回最终结果。 结果通过以下操作获得:val = fn(init, nums[0]), val = fn(val, nums[1]), val = fn(val, nums[2]), ... 直到处理完数组中的每个元素。然后返回 val 的最终值。 如果数组的长度为 0,则函数应返回 init。 请在不使用内置 Array.reduce 方法的情况下解决。 示例 1 输入 nums = [1,2,3,4] fn = function sum(accum, curr) { return accum + curr; } init = 0 输出: 10 说明 最初,值为 init=0。 (0) + nums[0] = 1 (1) + nums[1] = 3 (3) + nums[2] = 6 (6) + nums[3] = 10 最终答案是 10。 示例 2 输入 nums = [1,2,3,4] fn = function sum(accum, curr) { return accum + curr * curr; } init = 100 输出: 130 说明 最初,值为 init=100。 (100) + nums[0] * nums[0] = 101 (101) + nums[1] * nums[1] = 105 (105) + nums[2] * nums[2] = 114 (114) + nums[3] * nums[3] = 130 最终答案是 130。 示例 3 输入 nums = [] fn = function sum(accum, curr) { return 0; } init = 25 输出: 25 解释: 对于空数组,答案始终是 init。 约束 0 <= nums.length <= 1000 0 <= nums[i] <= 1000 0 <= init <= 1000 JavaScript 输出 Output: 10 Output: 130 Output: 25 问题 4给定一个函数数组 [f1, f2, f3, ..., fn],返回一个新函数 fn,它是函数数组的复合函数。 [f(x), g(x), h(x)] 的函数复合是 fn(x) = f(g(h(x)))。 空函数列表的函数复合是恒等函数 f(x) = x。 数组中的每个函数都接受一个整数作为输入并返回一个整数作为输出。 示例 1 输入: functions = [x => x + 1, x => x * x, x => 2 * x], x = 4 输出: 65 说明 从右到左求值... 从 x = 4 开始。 2 * (4) = 8 (8) * (8) = 64 (64) + 1 = 65 示例 2 输入: functions = [x => 10 * x, x => 10 * x, x => 10 * x], x = 1 输出: 1000 说明 从右到左求值... 10 * (1) = 10 10 * (10) = 100 10 * (100) = 1000 示例 3 输入: functions = [], x = 42 输出: 42 说明 零个函数的复合是恒等函数 约束 -1000 <= x <= 1000 0 <= functions.length <= 1000 所有函数都接受并返回单个整数 JavaScript 输出 Output: 65 Output: 1000 Output: 42 此代码 composeFunctions 函数反向遍历函数数组,通过将一个函数应用于另一个函数评估的结果来形成最终结果。如果函数数组为空,则返回 x 本身。 问题 5给定一个整数数组 arr 和一个映射函数 fn,返回一个应用了转换的新数组。 返回的数组应创建为 returnedArray[i] = fn(arr[i], i)。 请在不使用内置 Array.map 方法的情况下解决。 示例 1 输入: arr = [1,2,3], fn = function plusone(n) { return n + 1; } 输出: [2,3,4] 说明 const newArray = map(arr, plusone); // [2,3,4] 该函数将数组中的每个值增加一。 示例 2 输入: arr = [1,2,3], fn = function plusI(n, i) { return n + i; } 输出: [1,3,5] 解释: 该函数将每个值增加其所在的索引。 示例 3 输入: arr = [10,20,30], fn = function constant() { return 42; } 输出: [42,42,42] 解释: 该函数始终返回 42。 约束 0 <= arr.length <= 1000 -109 <= arr[i] <= 109 fn 返回一个数字 JavaScript 输出 Output 1: [2, 3, 4] Output 2: [1, 3, 5] Output 3: [42, 42, 42] 此代码指定了一个 map 函数,该函数将创建一个名为 mappedArr 的新数组,并迭代输入数组 arr 的每个元素。将相应的映射函数 fn 应用于每个元素,最后将结果推送到 mappedArr。最后,元素从原始数组 res 映射,从而产生一个包含转换后元素的新数组 mappedArr。 问题 6给定一个数组 arr 和一个块大小,返回一个分块数组。分块数组包含 arr 中的原始元素,但由长度为 size 的子数组组成。如果 arr.length 不能被 size 整除,则最后一个子数组的长度可能小于 size。 您可以假定数组是 JSON.parse 的输出。换句话说,它是有效的 JSON。 请在不使用 lodash 的 _.chunk 函数的情况下解决。 示例 1 输入: arr = [1,2,3,4,5], size = 1 输出: [[1],[2],[3],[4],[5]] 解释: arr 已被拆分成长度为 1 的子数组。 示例 2 输入: arr = [1,9,6,3,2], size = 3 输出: [[1,9,6],[3,2]] 解释: arr 已被拆分成长度为 3 的子数组。但是,第二个子数组只剩下两个元素。 示例 3 输入: arr = [8,5,3,2,6], size = 6 输出: [[8,5,3,2,6]] 解释: Size 大于 arr.length;因此,所有元素都在第一个子数组中。 示例 4 输入: arr = [], size = 1 输出: [] 解释: 没有要分块的元素,因此返回一个空数组。 约束 arr 是一个有效的 JSON 数组 2 <= JSON.stringify(arr).length <= 105 1 <= size <= arr.length + 1 JavaScript 输出 Output 1: [[1],[2],[3],[4],[5]] Output 2: [[1,9,6],[3,2]] Output 3: [[8,5,3,2,6]] Output 4: [] 此代码是一个示例,使用 chunkArray 作为函数名,它接受数组 arr 和块大小作为参数。它遍历数组,将其拆分成所需长度的子数组,并将每个子数组放入一个名为 chunkedArray 的新数组中。最后,它为您提供 chunkedArray。 问题 7创建一个 ArrayWrapper 类,该类在其构造函数中接受一个整数数组。此类应具有两个功能 当两个类的实例与 + 运算符相加时,结果值是两个数组中所有元素的总和。 当对实例调用 String() 函数时,它返回一个以逗号分隔并用方括号括起来的字符串,例如 [1,2,3]。 示例 1 输入: nums = [[1,2],[3,4]], operation = "Add" 输出: 10 说明 const obj1 = new ArrayWrapper([1,2]); const obj2 = new ArrayWrapper([3,4]); obj1 + obj2; // 10 示例 2 输入: nums = [[23,98,42,70]], operation = "String" 输出: "[23,98,42,70]" 说明 const obj = new ArrayWrapper([23,98,42,70]); String(obj); // "[23,98,42,70]" 示例 3 输入: nums = [[],[]], operation = "Add" 输出: 0 说明 const obj1 = new ArrayWrapper([]); const obj2 = new ArrayWrapper([]); obj1 + obj2; // 0 约束 0 <= nums.length <= 1000 0 <= nums[i] <= 1000 注意: nums 是传递给构造函数的数组JavaScript 输出 Output 1: 10 Output 2: [23,98,42,70] Output 3: 0 在此代码中,forward 类有一个构造函数,它接受一个整数数组作为参数。它还有两个方法:add() 是替换加法运算符的函数,结果是两个数组中所有元素的总和,toString() 是重写 toString 方法的函数,因此该函数返回一个用方括号括起来的字符串,中间有一个逗号分隔符。 问题 8编写一个函数 createHelloWorld。它应该返回一个新函数,该函数始终返回“Hello World”。 示例 1 输入: args = [] 输出: "Hello World" 说明 const f = createHelloWorld(); f(); // "Hello World" createHelloWorld 返回的函数应始终返回“Hello World”。 示例 2 输入: args = [{},null,42] 输出: "Hello World" 说明 const f = createHelloWorld(); f({}, null, 42); // "Hello World" 可以向函数传递任何参数,但它仍然应该始终返回“Hello World”。 约束 0 <= args.length <= 10 JavaScript 输出 Output 1: Hello World Output 2: Hello World 在此代码中,createHelloWorld() 返回一个新函数,该函数在被调用时,无论传递什么参数,始终返回“Hello World”。我们生成定义为 createHelloWorld() 的此函数的实例,并通过提供不同的参数集来调用它们,以表明该函数“Hello World”返回“Hello World”,而不管传递的参数如何。 问题 9给定一个函数 fn,一个参数数组 args,以及一个以毫秒为单位的超时时间 t,返回一个取消函数 cancelFn。 在 cancelTimeMs 延迟后,将调用返回的取消函数 cancelFn。 setTimeout(cancelFn, cancelTimeMs) 最初,函数 fn 的执行应延迟 t 毫秒。 如果在 t 毫秒的延迟之前调用了函数 cancelFn,它将取消 fn 的延迟执行。否则,如果 cancelFn 未在指定的延迟 t 内调用,则将使用提供的参数执行 fn。 示例 1 输入: fn = (x) => x * 5, args = [2], t = 20 输出: [{"time": 20, "returned": 10}] 说明 const cancelTimeMs = 50; const cancelFn = cancellable((x) => x * 5, [2], 20); setTimeout(cancelFn, cancelTimeMs); 取消操作计划在 cancelTimeMs (50ms) 延迟后发生,该延迟发生在 20ms 时 fn(2) 执行之后。 示例 2 输入: fn = (x) => x**2, args = [2], t = 100 输出: [] 说明 const cancelTimeMs = 50; const cancelFn = cancellable((x) => x**2, [2], 100); setTimeout(cancelFn, cancelTimeMs); 取消操作计划在 cancelTimeMs (50ms) 延迟后发生,该延迟发生在 100ms 时 fn(2) 执行之前,导致 fn(2) 永远不会被调用。 示例 3 输入: fn = (x1, x2) => x1 * x2, args = [2,4], t = 30 输出: [{"time": 30, "returned": 8}] 说明 const cancelTimeMs = 100; const cancelFn = cancellable((x1, x2) => x1 * x2, [2,4], 30); setTimeout(cancelFn, cancelTimeMs); 取消操作计划在 cancelTimeMs (100ms) 延迟后发生,该延迟发生在 30ms 时 fn(2,4) 执行之后。 约束 fn 是一个函数 args 是一个有效的 JSON 数组 1 <= args.length <= 10 20 <= t <= 1000 10 <= cancelTimeMs <= 1000 JavaScript 输出 For Example 1: [{"time": 20, "returned": 10}] For Example 2: [] For Example 3: [{"time": 30, "returned": 8}] 此代码中的 cancellable 函数接受主函数 fn、其参数以及延迟时间 t。它构造一个在 t 毫秒后解析的 promise,并在尚未被取消的情况下使用提供的参数执行函数 fn。另一方面,如果在超时之前调用了取消函数,则将 cancelled 标志设置为 true。最后,该图被包装在一个可能仍需取消的结束部分。 下一个主题Javascript-append |
我们请求您订阅我们的新闻通讯以获取最新更新。