二和 Leetcode 解释,Hashmap,Javascript

Posted

技术标签:

【中文标题】二和 Leetcode 解释,Hashmap,Javascript【英文标题】:Two-sum Leetcode explanation, Hashmap, Javascript 【发布时间】:2020-04-24 01:09:45 【问题描述】:

我只是想知道谁能一步一步解释这个解决方案的算法。我不知道哈希图是如何工作的。你能否也给我一个使用哈希图的基本例子来理解这个算法。谢谢!

var twoSum = function(nums, target) 
  let hash = ;

  for(let i = 0; i < nums.length; i++) 
    const n = nums[i];
    if(hash[target - n] !== undefined) 
      return [hash[target - n], i];
    
    hash[n] = i;
  
  return [];

【问题讨论】:

哈希映射只是一个简单的键-> js 中的值存储或对象。这里没有什么特别的,取样本输入并逐行检查代码。 【参考方案1】:

您的代码采用一个数字数组和一个目标数字/总和。然后它返回数组中两个数字的索引,这两个数字相加为目标数字/总和。

考虑一个数字数组,例如[1, 2, 3]5 的目标。你的任务是在这个数组中找到添加到5 的两个数字。解决此问题的一种方法是遍历数组中的每个数字并问自己“是否有一个数字(我已经在我的数组中看到过)可以添加到当前数字以获得我的 target 总和? ”。

好吧,如果我们遍历 [1, 2, 3] 的示例数组,我们首先从索引 0 开始,编号为 1。目前,我们已经看到没有任何数字可以与1 相加来获得5 的目标,因为我们还没有循环任何数字。

到目前为止,我们遇到了编号1,它位于索引0。它以'1': 0 的形式存储在hashmap(即对象)中。其中键是数字,值 (0) 是它所在的索引。该对象的目的是存储我们看到的数字以及它们出现的索引。

接下来,循环继续索引 1,当前编号为 2。我们现在可以问自己一个问题:是否有一个我已经在我的数组中看到的数字可以添加到我当前的 2 数字以获得 5 的目标总和。可以通过执行target-currentNumber 获得要添加到当前数字以达到目标所需的数量。在这种情况下,我们当前位于2,因此我们需要添加3 以达到我们的目标总和5。使用hashmap/object,我们可以检查我们是否已经看到了数字3。为此,我们可以尝试通过执行obj[target-currentNumber] 访问对象3 键。目前,我们的对象只有'1' 的键,所以当我们尝试访问3 键时,您将得到undefined。这意味着我们还没有看到数字 3,因此,到目前为止,我们无法将任何内容添加到 2 以获取我们的 target 总和。

所以现在我们的对象/hashmap 看起来像'1': 0, '2': 1,因为我们看到了索引1 处的数字0,我们看到了索引1 处的数字2

最后,我们到达了数组中的最后一个数字,即索引 2。数组的索引 2 包含数字 3。现在,我们再次问自己一个问题:是否有一个我们已经看到的数字可以添加到3(我们当前的数字)以获得target 的总和?我们需要添加到3 以获得5 的目标数量是2(通过执行target-currentNumber 获得)。我们现在可以检查我们的对象,看看我们是否已经在数组中看到了一个数字2。为此,我们可以使用obj[target-currentNumber] 来获取存储在键2 中的值,该键存储1 的索引。这意味着数组中确实存在数字2,因此我们可以将其添加到@ 987654365@达到我们的目标。由于值在对象中,我们现在可以返回我们的发现。那是看到的数字出现的索引,以及当前数字的索引。

一般来说,该对象用于跟踪数组中所有以前看到的数字,并保留看到该数字的索引值。

这是运行代码的示例。它返回[1, 2],因为索引12 处的数字可以相加得到5 的目标总和:

const twoSum = function(nums, target) 
  const hash = ; // Stores seen numbers: seenNumber: indexItOccurred

  for (let i = 0; i < nums.length; i++)  // loop through all numbers
    const n = nums[i]; // grab the current number `n`.
    if (hash[target - n] !== undefined)  // check if the number we need to add to `n` to reach our target has been seen:
      return [hash[target - n], i]; // grab the index of the seen number, and the index of the current number
    
    hash[n] = i; // update our hash to include the. number we just saw along with its index.
  
  return []; // If no numbers add up to equal the `target`, we can return an empty array


console.log(twoSum([1, 2, 3], 5)); // [1, 2]

这样的解决方案可能看起来设计过度。您可能想知道为什么不能只查看数组中的一个数字,然后查看所有其他数字,看看您是否遇到了一个加起来等于target 的数字。这样的解决方案可以很好地工作,但是,它不是很有效。如果您的数组中有 N 个数字,在最坏的情况下(没有两个数字加起来等于您的 target),您需要遍历所有这些 N numbers - 这意味着您将进行 N 次迭代。但是,对于您查看单数的每次迭代,您都需要使用内部循环查看其他数字。这意味着对于您的外循环的每次迭代,您都会对您的内循环进行 N 次迭代。这将导致您进行 N*N 或 N2 工作(O(N2) 工作)。与这种方法不同,本答案前半部分描述的解决方案只需要对整个数组进行 N 次迭代。使用对象,我们可以在常数(O(1))时间内找到一个数字是否在对象中,这意味着上述算法的总工作量只有O(N)。

有关对象如何工作的更多信息,您可以阅读括号表示法和其他属性访问器方法here。

【讨论】:

有点明白。但是除了这两个和问题之外,还有其他使用他的 Hashmap 的例子让我完全理解它吗?任何基本示例 @JamesA 嗨,我添加了一些关于对象的更多详细信息以及一个示例,您可以使用对象来计算数组中事物的频率 谢谢您的好先生。在这个频率示例中,我得到了这个,它类似于直方图,用于跟踪数组中有多少个字母。但是,我有点困惑理解这个 leetcode 示例使用 hashmap/obj 返回 2 个值。 @JamesA leetcode 使用 array 返回 2 个值。它将数组中的第一项设置为我们需要与当前数字相加以达到目标总和的数字的索引。数组中的第二个值是当前数字的索引。因此,这给了我们一个由两个数字组成的数组,它们代表原始数组中出现两个数字的索引,当它们相加时,我们得到了目标总和。 @MikiBelavista 谢谢 :) 当没有两个数字可以相加等于目标总和时,代码返回一个空数组[]。由于 return [] 出现在 for 循环之后,因此只有在我们遍历数组中的每个数字后,它才会返回空数组。如果我们碰巧在循环中找到两个加起来等于目标总和的有效数字,我们将返回 [hash[target - n], i] 而不是空数组。返回一个空数组只是表示两个数字可以相加到达target的一种方式。【参考方案2】:
function twoSum(numbers, target) 
  for (let i = 0; i < numbers.length; i++) 
  for (let j = i + 1; j < numbers.length; j++) 
    if (numbers[i] + numbers[j] === target) 
      return [numbers.indexOf(numbers[i]), numbers.lastIndexOf(numbers[j])];
    
  


【讨论】:

欢迎来到 ***!请访问Help Center,拨打tour 并在此处阅读writing good answers。仅代码的答案在这里总是不受欢迎;当问题要求对现有算法进行解释时,尤其如此。 既然已经有了 i 和 j,为什么还要使用 indexOf 和 lastIndexOf?【参考方案3】:

常量数 = [1,5,9];

const twoSum = (nums, target) => // O(n)

let map = ; //O(n)
for (let i = 0 ; i < nums.length ; i++)
    var value = nums[i];
    var complementPair = target - value;

    if (map[complementPair] !== undefined)
        return [map[complementPair],i];
    
    map[value] = i;


console.log(twoSum(array1, 10));

【讨论】:

以上是关于二和 Leetcode 解释,Hashmap,Javascript的主要内容,如果未能解决你的问题,请参考以下文章

了解为啥我的 C# 中的二和(LeetCode 问题)代码不适用于 [1,2] 的预期答案

理解二和leetcode问题(Ruby)

LeetCode Q1 二和单遍哈希表不工作

LeetCode 3. 无重复字符的最长子串(动态规划,HashMap,Java)

LeetCode 3. 无重复字符的最长子串(动态规划,HashMap,Java)

离职第二和第三个月总结 2018.10