在循环内使用 indexOf 是一个坏主意吗?
Posted
技术标签:
【中文标题】在循环内使用 indexOf 是一个坏主意吗?【英文标题】:Is it a bad idea to use indexOf inside loops? 【发布时间】:2017-01-20 16:05:45 【问题描述】:我正在为一次技术面试学习大 O 表示法,然后我意识到 javascript 的 indexOf
方法可能具有 O(N) 的时间复杂度,因为它遍历数组的每个元素并返回找到它的索引。
我们还知道,O(n^2)(n 平方)的时间复杂度对于较大的数据并不是一个好的性能指标。
那么在循环内使用indexOf
是个坏主意吗?在 javascript 中,在循环中使用indexOf
方法的代码很常见,可能是为了衡量相等性或准备一些对象。
我们是否应该在必要时首选对象而不是数组,因为它们提供具有恒定时间性能 O(1) 的查找。
任何建议将不胜感激。
【问题讨论】:
【参考方案1】:在循环内使用indexOf
可能是个坏主意,尤其是当您正在搜索的dataStructure
非常大时。
解决此问题的一种方法是拥有一个哈希表或字典,其中包含您可以在O(N)
时间生成的每个项目的索引,方法是循环遍历数据结构并在每次添加到数据结构时更新它。
如果你 push
在数据结构的末尾有一些东西,它将花费 O(1)
时间来更新这个表,最坏的情况是如果你将一些东西推到数据结构的开头,它将花费 O(N)
.
在大多数情况下,这是值得的,因为获取索引将是 O(1)
时间。
【讨论】:
【参考方案2】:说实话,tl;博士。但是,我对检查字符串中出现的各种方法进行了一些速度测试(如果这是您使用 indexOf 的目标。如果您实际上是在尝试获取匹配的位置,我个人不知道如何提供帮助你在那里)。我测试的方式是:
.includes()
.match()
.indexOf()
(还有.search()
、.lastIndexOf()
等变种,我没测试过)。
这是测试:
var test = 'test string';
console.time('match');
console.log(test.match(/string/));
console.timeEnd('match');
console.time('includes');
console.log(test.includes('string'));
console.timeEnd('includes');
console.time('indexOf');
console.log(test.indexOf('string') !== 0);
console.timeEnd('indexOf');
我知道它们不是循环,但向您展示它们的速度基本相同。老实说,每个人都做不同的事情,这取决于你的需要(你想用 RegEx 搜索吗?你需要预先兼容 ECMAScript 2015 吗?等等 - 我什至没有列出所有这些)是否真的有必要分析就这么多?
根据我的测试,有时indexOf()
会赢,有时其他一个会赢。
【讨论】:
您提到的所有上述解决方案可能会提供相同的性能,因为输入非常非常小。我主要关心的是数据量要大得多。以上是关于在循环内使用 indexOf 是一个坏主意吗?的主要内容,如果未能解决你的问题,请参考以下文章