【问题标题】:What is the time complexity of javascript's array.indexOf?javascript array.indexOf的时间复杂度是多少?
【发布时间】:2013-10-10 04:24:57
【问题描述】:

indexOf 是简单地遍历数组还是做一些更快的事情? 我知道这取决于实现,但 Chrome 或 Firefox 是做什么的?

【问题讨论】:

  • 你应该去一个你关心的实现的开发者的邮件列表并在那里询问。由于 ECMAScript 类似于 Java,我希望开发人员尽可能利用底层平台原生方法,因为大多数已经为此优化了函数。但这只是猜测。
  • Firefox 实现可见here。 @GameAlchemist 请控制您的挫败感并将其引导至 SO...上的 close 按钮等按钮...

标签: javascript


【解决方案1】:

找到第一个与未排序数组中的值匹配的索引的最有效方法是按顺序遍历列表,即 O(n)。 MDN也有一些提示:

返回可以在数组中找到给定元素的第一个索引,如果不存在,则返回 -1。

[...]

从索引

默认值:0(搜索整个数组)
开始搜索的索引。如果索引大于或等于数组的长度,则返回-1,表示不会搜索该数组。如果提供的索引值为负数,则将其作为距数组末尾的偏移量。注意:如果提供的索引为负数,仍会从前向后搜索数组。如果计算的索引小于 0,则将搜索整个数组

如果你想知道,here's how WebKit implements it:

EncodedJSValue JSC_HOST_CALL arrayProtoFuncIndexOf(ExecState* exec)
{
    // 15.4.4.14
    JSObject* thisObj = exec->hostThisValue().toThis(exec, StrictMode).toObject(exec);
    unsigned length = thisObj->get(exec, exec->propertyNames().length).toUInt32(exec);
    if (exec->hadException())
        return JSValue::encode(jsUndefined());

    unsigned index = argumentClampedIndexFromStartOrEnd(exec, 1, length);
    JSValue searchElement = exec->argument(0);
    for (; index < length; ++index) {
        JSValue e = getProperty(exec, thisObj, index);
        if (exec->hadException())
            return JSValue::encode(jsUndefined());
        if (!e)
            continue;
        if (JSValue::strictEqual(exec, searchElement, e))
            return JSValue::encode(jsNumber(index));
    }

    return JSValue::encode(jsNumber(-1));
}

【讨论】:

  • 谢谢,所以如果我知道我正在使用的数组已排序,我最好使用二进制搜索的自定义实现,因为它具有O(log(N)) 的更好复杂性?
  • @Maximus 这取决于数组的大小,但如果它足够大以至于这很重要,那么值得一试。我会对其进行基准测试,以确保您不会通过用 JavaScript 函数替换内置(C++)函数来使其变慢(对于小型N,C++ 中效率较低的算法可能会击败更有效的算法JavaScript)。
【解决方案2】:

由于不能保证数组中项目的性质或顺序,你不能做得比 O(n) 更好,所以它会遍历数组。即使它是跨 CPU 并行化实际搜索(不知道 firefox 或 chrome 是否这样做,但他们可以),它不会改变 CPU 数量有限的时间复杂度。

【讨论】:

  • JS 数组不是顾名思义的常规数组,而是哈希映射。除了键之外,还可以只为值创建第二个索引,从而为值查找提供更好的时间复杂度以换取内存使用。
  • @Casey 值得注意的是,JS 数组 JS 对象 - 只是带有整数键和一些附加方法。来自Mozilla Array docs:“数组是类似列表的对象,其原型具有执行遍历和变异操作的方法。”您可以通过运行Object.keys(['a', 'b']);Object.values(['a', 'b']); 亲自查看数组使用键/值对。
【解决方案3】:

在 ECMA6 中,你有 Set(),然后你可以这样做:

var obj = new Set();
obj.add(1);
obj.has(1) === true;
obj.has(2) === false;

has 的性能是 O(1)。

【讨论】:

  • has() 肯定比indexOf() 快,但我们不确定元素的顺序是否对原始帖子作者有任何不同...
  • 是的,它没有太多信息,但我只是想展示另一种可能性!谢谢
  • @StefanoSaitta 没有它的 O(1) stackoverflow.com/questions/31091772/…
  • 这不能回答问题
  • 如果把数组转换成集合,那不还是O(n)吗?
猜你喜欢
  • 2017-03-19
  • 2021-02-10
  • 2018-11-24
  • 2014-05-27
  • 1970-01-01
  • 1970-01-01
  • 2013-09-09
  • 2020-07-01
  • 2021-08-03
相关资源
最近更新 更多