You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

算法题:无序数组最大n个数求和的实现规范与复杂度疑问

问题:无序数组最大n个数求和的实现疑问

参考实现代码

const list_sum_largest_n_numbers = (list: Array<number> = [], n: number) => {
  let sum: number = 0;
  const sorted_list = list.sort((a, b) => a - b);

  for (let i = 0; i < n; i++) {
    let value_to_sum = sorted_list?.pop() || 0;
    sum += value_to_sum;
  }

  return sum;
};

let list = [17, 310, 32_432, 3, 2, 317, 34, 108_379];
let n = 3;

let result = list_sum_largest_n_numbers(list, n);
alert(result); // 141_128

注:上述实现存在一个副作用:Array.sort()是原地排序方法,会直接修改传入的原数组,若业务场景不允许修改入参,需要先对数组做浅拷贝再排序。

疑问解答

1. 算法题是否允许使用编程语言内置方法?

完全分场景判断,没有统一的“必须手动实现底层”的要求:

  • 日常业务开发:优先使用内置方法,内置方法都是经过厂商高度优化、边界case覆盖全面的工业级实现,重复造底层轮子反而会引入不必要的bug和性能问题。
  • 算法竞赛(如OJ平台刷题):只要编程语言语法支持,没有任何规则限制使用内置方法,只要最终代码的时间、空间复杂度符合题目要求,能通过所有测试用例即可。
  • 技术面试/笔试:如果题目没有明确要求“手动实现排序/禁止使用内置排序接口”,可以直接用内置方法,但算法岗面试中面试官大概率会追问你所用内置方法的实现逻辑、复杂度开销,也可能进一步要求你写出更适配当前场景的优化解法,需要提前准备相关知识。

2. 当前实现的复杂度与最优解法说明

你当前的实现时间复杂度不是O(n):JS/TS主流运行时(如V8引擎)的Array.sort()采用TimSort实现,平均时间复杂度为O(m log m)(m为输入数组的长度),后续取n个最大值求和的时间复杂度为O(n),因此整体复杂度为O(m log m)。

这个解法不是所有场景下的最优解,针对该问题有更适配的方案,选择哪种取决于n和数组长度m的相对大小:

  • 当n远小于m时(比如从百万级数据里取前10大的数求和),最常用的优化方案是维护一个大小为n的最小堆:遍历整个数组,堆中始终保存当前遍历到的最大的n个数,堆顶是这n个数里的最小值;如果新遍历到的数比堆顶大,就弹出堆顶、把新数放入堆中调整结构,遍历完成后对堆中所有元素求和即可。该方案时间复杂度为O(m log n),相比全排序性能提升非常明显。
  • 理论平均复杂度最优的是基于快速选择的解法:借鉴快排的分区(partition)思路,通过随机选择枢轴的方式,平均仅需O(m)的时间复杂度就能把所有比第n大数大的元素划分到数组一侧,之后直接对这部分元素求和即可,最坏时间复杂度为O(m²),但随机选枢轴的实现可以把最坏情况出现的概率降到几乎可以忽略。该方案缺点是常数项比堆方案高,且实现逻辑更复杂,容易写错边界。
  • 当n和m的大小接近时(比如要取数组前90%大的数求和),你当前用内置排序的解法反而是实际运行效率最高的——内置排序是引擎层面高度优化的实现,常数项极低,实际表现会优于手写的堆、快选实现。

内容的提问来源于stack exchange,提问作者Emille C.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 21:00:54