algorithm - 对未排序数组中最大的 n 个数求和

标签 algorithm

只是想解决这个问题:

给定一个未排序的整数数组,对它最大的 n 个数求和。

我做了一个 TypeScript 实现,但这当然与语言无关:

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

playground 中.

我的第一个问题是,在解决这类问题时,是否允许使用语言提供的方法——如 Array.sort()——,或者我是否应该通过我自己,将解决方案保持在低水平。

此外,我不确定这是解决问题的最佳方法。我会说这是 O(n),但我没有考虑我正在使用的 Array.sort() 方法。

最佳答案

排序已经是 O(n logn)。当使用内置排序功能时,它可能是一个简单的解决方案,但它不会是解决问题的最有效解决方案。

简单的解决方案 O(kn)

如果您正在为这个问题寻找更有效但更简单的解决方案,您可以通过迭代不断挑选(并删除或标记为已访问)最大数 k 次。您可以随时将它们加在一起,而不必将它们存储在一个新数组中并再次迭代。这实际上是每个数字 O(n),因此总共 O(kn)

这对于小的或恒定的 k 会更有效。当然,例如,如果您知道 k = O(n),则存在更好的方法。

高效的解决方案 O(n)

对于稍微简单一点的解决方案,您可以使用 Quickselect找到第 k 个最大的数 x 然后在一次迭代中将所有大于 x 的数加在一起,然后加上 x 和可能剩余的重复值(或者如 rici 指出的那样,只在 x 的右侧迭代,因为 quickselect 对数组进行分区对我们有利)。这将为您提供 O(n) 加法运算的总时间复杂度。这是渐近性能和代码复杂性之间的权衡:)

关于使用内置排序

至于是否可以使用内置函数:可以,可以。每当它们适合您的目的时,最好使用它们而不是每次都重新发明轮子。但是,在学术或挑战环境中,出于教育或竞争原因,可能存在禁止使用库或内置函数的规则。

关于algorithm - 对未排序数组中最大的 n 个数求和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72620600/

相关文章:

algorithm - 如何查找 3D 对象是否适合另一个 3D 对象(容器)?

java - 如何在 O(n) 时间内找到到达数组末尾的最少跳转次数

algorithm - 如果叶子从左到右的顺序是固定的,那么有多少棵二叉树?

ruby - 如何将 "email@domain.com"转换为 "em***@domain.com"?

java - 快速排序比 Java 中的插入排序和选择排序慢多少?

一行代码中的 C strlen() 实现

algorithm - 如何找出给定圆的周长有多少被其他相交的圆覆盖?

c++ - 从 char 数组中删除条目

arrays - 如何在随机排列的连续整数数组中找到重复元素?

iphone - 在 iOS 上应用带通滤波器