Array函数的JavaScript运行时复杂性

时间:2014-03-24 15:51:31

标签: javascript arrays time-complexity

JS标准在Arraypushpopshiftslice等常见splice函数上定义的运行时复杂性? ESP。我有兴趣在随机位置删除和插入条目。如果没有定义复杂性,我可以期待什么,例如在V8?

(这个问题的灵感来自于this。此外,this benchmark,张贴here,也让我很好奇,但也许这是一些无关的现象。)

(一个非常相关的问题是here。然而,关于接受的答案的评论之一说现在是错的。而且,接受的答案没有任何参考标准真正定义它的方式)。

4 个答案:

答案 0 :(得分:64)

ECMA规范没有指定边界复杂性,但是,您可以从规范的算法中派生出一个。

push O(1),但实际上它会在引擎定义的边界处遇到 O(N)复制成本作为插槽数组需要重新分配。这些边界通常是对数的。

pop O(1)push有类似的警告,但很少遇到 O(N)副本,因为它是经常被折叠成垃圾收集(例如,复制收集器只能复制数组的已使用部分)。

shift最差 O(N)然而,在特殊情况下,它可以以降低速度为代价实现为 O(1)索引,所以你的里程可能会有所不同。

slice O(N),其中 N end - start。这里没有大量的优化机会,也没有显着减慢对两个阵列的写入速度。

splice是最坏的情况, O(N)。有一些数组存储技术可以将 N 除以常量,但它们会显着减慢索引速度。如果引擎使用这种技术,您可能会注意到异常缓慢的操作,因为它在访问模式更改触发的存储技术之间切换。

你没有提到的是sort。在一般情况下,它是 O(N log N)。但是,根据引擎选择的算法,在某些情况下可以获得 O(N ^ 2)。例如,如果引擎使用QuickSort(即使延迟到InsertionSort),它也有众所周知的 N ^ 2 情况。这可能是您的应用程序的DoS源。如果这是一个问题,要么限制你排序的数组的大小(可能合并子数组)或纾困到HeapSort。

答案 1 :(得分:2)

用非常简单的话

推-> O(1)

pop -> O(1)

移位 -> O(N)

切片 -> O(N)

拼接 -> O(N)

Here 是对 JavaScript 中数组时间复杂度的完整解释。

答案 2 :(得分:0)

仅需注意,可以使用RingBuffer(iow CircularQueue / CircularBuffer)在O(1)中实现const flipPairs = str => str.replace(/(.)(.)/g, '$2$1'); console.log(flipPairs("hello world")); / shiftunshift / push方法数据结构。每当不需要循环缓冲区增长时,最坏的情况就是O(1)。有人实际衡量过这些操作的绩效吗?总是比不猜测更容易知道...

答案 3 :(得分:-3)

如果采用的数量未知,

切片只是线性的。如果切片编号是常数,则切片是常量,而不是线性。