【问题标题】:Does the JavaScript "in" operator execute a loop under the hood? [duplicate]JavaScript“in”运算符是否在后台执行循环? [复制]
【发布时间】:2019-07-31 09:24:44
【问题描述】:

我正在研究一些常见算法的解决方案,并且遇到了一些我很好奇的东西。我试图通过谷歌搜索并查看一些规范来自己找到答案,但我无法找到我的问题的答案。下面的算法基本上检查第一个数组中的每个项目是否在第二个数组中都有对应的项目平方。天真的解决方案(正如他们所说)将具有某种嵌套循环并被视为 O(n2)。写下面解决方案的人说这是O(n)。

我不明白这怎么可能是 O(n),因为他在循环中使用了 Javascript“in”运算符。据我所知,操作员检查它所比较的​​值是否存在于对象中。 如果它不循环通过引擎盖下的对象,它是如何做到的?这真的是线性时间复杂度吗?

function same(arr1, arr2) {

  if (arr1.length !== arr2.length) {
    return;
  }

  let frequencyMap1 = {};
  let frequencyMap2 = {};

  for (let val of arr1) {
    frequencyMap1[val] = (frequencyMap1[val] || 0) + 1;
  }

  for (let val of arr2) {
    frequencyMap2[val] = (frequencyMap2[val] || 0) + 1;
  }

  for (let key in frequencyMap1) {
    if (!(key ** 2 in frequencyMap2)) {
      return false;
    }

    if (frequencyMap2[key ** 2] !== frequencyMap1[key]) {
      return false
    }
  }

  return true;
}

console.log(same([1, 2, 3], [1, 4, 9])); // true

【问题讨论】:

  • ** 在做什么,我的意思是它应该做什么?
  • 它基本上是对第一个数组的值进行平方。我猜你可以把它想象成 key * key。
  • @NinaScholz 这是 ES2016 中引入的 exponentiation operator
  • 我知道它在做什么,但为什么在代码中?
  • @JonasWilms,哦,对了,谢谢。我也应该读一下案文。这对我来说太散文了。

标签: javascript algorithm


【解决方案1】:

在对象中找到一个键是 O(1)for .. in 和只有 in 运算符不同。

无论一个对象中有多少个键,您都可以在恒定时间内访问它。 ObjectMap 有一个哈希表来查找密钥。

【讨论】:

  • 我知道在键/值中查找值是不变的。我不知道找到密钥的机制相同。
  • 更清楚一点,for...in 是 O(n),而 in 是 O(1)。
  • @aaron 哈希表通常是一个键值对列表,这些键值对基于散列键存储在一个数组中。要从键中获取值,会生成散列,在键散列位置进行搜索(因为散列可能会发生冲突),并找到具有所需键的对,并返回值。 in 做同样的事情,只是它不返回值。
  • @Jonas,谢谢。
【解决方案2】:

infor-in 的不同答案:

in 操作符查看一个对象(如果有必要,它的原型和它的 原型等),以查看该对象是否具有具有给定名称的属性。在任何甚至是半体面的 JavaScript 引擎中,除了通过原型链的循环之外,这不会涉及循环(在一个好的 JavaScript 引擎上,甚至不会,因为在一个好的 JavaScript 引擎上,对象被实现为 JIT 类,所以他们知道它们的结构)。

for-in 循环遍历对象及其原型中可枚举属性的名称。很自然,这涉及到一个循环(可能是嵌套的,因为涉及到原型链)。

【讨论】:

    【解决方案3】:

    这取决于。规范不保证对象的查找时间,因此这可能是 O(n²) 最坏的情况。但是,如果您使用许多不同的键,大多数引擎会将对象表示为 hashtables,然后查找时间为 O(1),算法运行时间为 O(n)。

    【讨论】:

    • 在哈希表上,O(1) 只是 平均 的情况。最坏的情况仍然是 O(n),所以假设您在使用 for...in 循环时仍然可以处理 O(n²) 最坏的情况。
    • @patrick 会假设所有哈希都发生冲突,我敢打赌这不会发生在所有键上,所以我认为我们可以安全地假设这种“假设”情况永远不会发生。跨度>
    • 我只是指出存在明显的可能性,但可能性很小。相比之下,数组和典型的对象原型存储在顺序内存中,因此对于这些类型的对象,在所有情况下访问真正是 O(1),而不是由哈希表支持的对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 2020-04-13
    • 1970-01-01
    • 2020-09-08
    • 1970-01-01
    • 1970-01-01
    • 2015-11-04
    相关资源
    最近更新 更多