找出数组中第二大整数:哪种JavaScript实现方法更高效?
哪种找数组第二大整数的实现更高效?
毫无疑问,第二段代码的实现效率更高,下面从时间复杂度、实际运行开销两个层面拆解原因:
第一段代码的开销分析
这段代码的逻辑是先找最大值、删去最大值,再找新的最大值:
Math.max(...numbers):遍历整个数组找出最大值,时间复杂度O(n)numbers.indexOf(...):再次遍历数组找最大值的索引,时间复杂度O(n)numbers.splice(max, 1):删除指定位置元素,数组后面的元素需要集体移位,时间复杂度O(n)- 第二次
Math.max(...numbers):又一次遍历数组找最大值,时间复杂度O(n)
总时间复杂度是O(n),但实际要执行4次完整的数组遍历(或近似遍历),常数项开销大。另外还有两个隐性问题:
- 会直接修改原数组,可能导致意料之外的副作用
- 如果数组规模极大,
...numbers展开参数时可能触发栈溢出
第二段代码的开销分析
这段代码只做一次数组遍历:
遍历过程中维护first(当前最大值)和second(当前第二大值)两个变量,每遍历一个元素就通过条件判断更新这两个变量,全程只需要O(n)的时间复杂度,而且只执行一次遍历,常数项开销远低于第一段代码。
同时它不会修改原数组,也没有参数展开的风险,在大数组场景下的优势会更明显。
补充:边界情况的逻辑差异
虽然你问的是效率,但提一句:两段代码的逻辑在某些场景下结果不同。比如数组存在多个相同最大值时(如[45,45,24]),第一段代码删除一个最大值后会返回45,而第二段代码因为arr[i] != first的限制,会返回初始值-1——如果需要处理这种场景,第二段代码可以去掉arr[i] != first的判断,逻辑会更合理。
内容的提问来源于stack exchange,提问作者Waail
相关产品推荐
相关产品推荐

