【问题标题】:How to generate k largest subset sums for a given array (contains positive and negative numbers)如何为给定数组生成 k 个最大子集和(包含正数和负数)
【发布时间】:2022-06-25 20:32:05
【问题描述】:

所以问题很简单,给定一个大小为 N( N

我们必须按降序输出。

有没有办法以低于指数的复杂性做到这一点。 我的想法是 如果要生成2^N个item,复杂度怎么可能小于2^N,

在amazon OA中问(问题叫find k maximum priority)

【问题讨论】:

  • 显而易见的答案是您不必生成所有 2^N 项。例如,您可以通过一次遍历数组(即 O(N))找到最大子集和。
  • 它的最小值为 (2000,2^N),因为 2^N 是数组可以拥有的子集数量上限。所以复杂度不会是 2^N
  • 我得到了这个方法,但我有一些疑问。我们将只取所有正元素的总和,然后我们可以选择删除最小的正元素或添加最小的负数来得到下一个和,所以为了做到这一点,我们可以只存储 Math.abs最小堆中的所有数字,并从 maxSum 中减去最小堆的输出以获得下一个最大的和。但这是否足够,因为使用这种方法,我们只能正确生成 N+1 个和。我刚刚重新检查了约束,它是 k
  • 如果你的方法只能产生 N+1 个和,而 k>N+1,你就输了。

标签: algorithm


【解决方案1】:

我只是概述一下。由您来实施它并证明它有效。

首先,在单遍中,我们找到正数的总和。这是最大的总和。我们用[maximum_sum]初始化我们的答案数组。

接下来,我们创建一个绝对值数组av,从小到大排序。

接下来,我们创建一个优先级队列upcoming。它将从其中的一对开始。那对将是(maximum_sum - av[0], 0)。这些对首先按字典顺序与最大和进行比较。

直到answer 中有足够的元素,我们将:

get (next_sum, i) from upcoming
add next_sum to answer
if i < N:
    add (next_sum + av[i] - av[i+1], i+1) to upcoming
    add (next_sum - av[i+1], i+1) to upcoming

此算法将使用O(N+k) 内存和O(N log(N) + k log(k)) 工作来生成顶部k 答案。它取决于Nk,但两者都不是指数级的。

【讨论】:

  • 哇,你是怎么想到这个的
  • 所以我们取当前的 maxSum ,看看哪个元素被删除来形成当前的 maxSum ,然后我们选择是否添加回第 i 个元素。你是个天才,我的朋友。你是如何从 2^n 递归方法中得出这个的,想知道你的思维过程
  • @BosssMan861 我刚刚做了很多。
【解决方案2】:

我将描述一个更简单的解决方案:

A 是初始数组,让PosNeg 分别是来自A 的所有正数(准确地说是非负数)和所有负数的集合。

让我们从另一个角度来看问题。而不是从A 中选择子集 并最小化正数和负数的总和,我们将考虑一个等价的问题:

MaxSum := Pos 中所有数字的总和。显然,这是我们能得到的最大金额。 从MaxSum 开始,我们可以通过从Neg 中添加一些数字并从Pos 中减去一些数字来获得A 的任何子集和。请注意,这两个操作都会从 MaxSum! 中减去一些 非负 值!因此,我们将问题简化为一个更简单的问题:

更简单的问题:Abs := PosNeg 的绝对值集( A 的所有绝对值集)。 我们需要从Abs 中选择k 的最小和减去 MaxSum

解决方案: 取最小的m,例如2^m &gt;= min(2^N, k)。受问题的约束,我们有m &lt;= 11。 显然,来自Absk 最小和是Abs 的最小m 数的一些子集。 因此,我们可以考虑所有这些2^m &lt;= 2048 子集并得到最小的和 (s_1, s_2, ... s_k)。最终答案将是(MaxSum - s_1, MaxSum - s_2, ... MaxSum - s_k)

时间复杂度:

  1. O(N)MaxSum
  2. O(N log(N)),例如,从Abs 中查找m 的最小数字。事实上,找到m 最小的数字可以通过O(N + m log(m)) 复杂性来完成,请参阅this。由于m &lt;= 11,我们可以说时间复杂度也是O(N)
  3. O(1) 考虑来自 m 数字的 2^m &lt;= 2048 和(例如,使用位掩码)。

总时间复杂度O(Nlog(N)) 用于直接方法,O(N) 用于优化方法。

空间复杂度:O(N + k)O(N),因为k &lt;= 2000)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-04
    • 2019-09-19
    • 2013-03-05
    • 2021-09-16
    • 1970-01-01
    • 1970-01-01
    • 2021-05-23
    • 2023-03-09
    相关资源
    最近更新 更多