学习在JavaScript中的二和编码挑战解决方案

49 阅读2分钟

简介

几周前,我探讨了二和编码挑战的问题,并讨论了解决它的低效和高效方法。今天,我对高效的解决方案进行了改进,提供了一个对JavaScript来说更习惯的解决方案。

二和问题

首先,让我们了解一下二和问题。它通常是以下面的某种形式提出的。

你被要求创建一个需要两个参数的函数。第一个参数,nums ,是一个数组。第二个参数,total ,是一个单一的数字。该函数的输出应该是一个双元素数组,代表nums 中的一对数字,它们的总和为total

/**
 * @param {number[]} nums
 * @param {number} total
 * @return {number[]}
 */
const twoSum = (arr, total) => {
  // Solution here
};

通常情况下,我们会得到几个有效的输入/输出组合的例子。

input: nums = [1, 2, 3], total = 4
output: [1, 3]

input: nums = [3, 9, 12, 20], total = 21
output: [9, 12]

以前的解决方案

在我之前的博文中,我得出了以下解决方案。它只需要在数组中迭代一次,在迭代过程中向一个对象添加元素。然后,它在该对象中搜索一个 "补充 "值,以配合当前的数组元素。由于对象的哈希表效率,该解决方案的时间复杂度为O(n)。

const twoSum = (nums, total) => {
  const previousValues = {};
  for (let i = 0; i < nums.length; i++) {
    const complement = total - nums[i];
    if (previousValues[complement]) {
      return [complement, nums[i]];
    }
    previousValues[nums[i]] = true;
  }
};

一个更简明的方法

实际上,JavaScript有一个特定的对象可以帮助解决这个问题:Set 对象Set 是 "更成文的",因为它是一个存储唯一值(或对象引用)的机制,而不必做我上面做的奇怪的previousValues[nums[i]] = true; 工作。

如果我们改变我们的实现以使用Set ,它可能看起来如下。

const twoSum = (nums, total) => {
  const previousValues = new Set();
  for (let i = 0; i < nums.length; i++) {
    const complement = total - nums[i];
    if (previousValues.has(complement)) {
      return [complement, nums[i]];
    }
    previousValues.add(nums[i]);
  }
};

根据EcmaScript 2015规范,"集合对象必须使用哈希表或其他机制来实现,这些机制平均提供的访问时间是集合中元素数量的次线性。"因此,我们不一定确定Set 将使用哈希表实现,但我们可以对其效率有信心。

总结

对象缓存和Set 方法都能有效地解决二和问题,但Sets似乎是在JavaScript中处理这个问题的更习惯的方式