如何找到算法:给定一个整数数组,整数子集的最大总和是多少

时间:2011-11-04 08:47:01

标签: algorithm

给定一个整数数组,整数子集的最大总和是多少,这样子集中的整数最初并不是彼此相邻?

示例:

[3, 8, 4] => max sum is 8, since 8 > (3+4)
[12, 8, 9, 10] => max sum is 12 + 10 = 22, since this is greater than 12 + 9 and 8 + 10

我有兴趣找出执行此操作的算法。方法/思维过程=非常感谢。

编辑: 整数范围从1到1000,包括1和1000。 (由于这完全是一个学习练习,如果整数范围从-1000到1000,我仍然有兴趣学习不同的方法。)

4 个答案:

答案 0 :(得分:8)

让你有数组A {Ai, 1 <= i <= n }

F(i) - 子阵列Aj { 1 <= j <= i }的最大总和,然后是

F(0) = 0 - 空子阵列

F(1) = A(1) - 只有第一个元素

F(i) = max(F(i-2) + A(i), F(i-1)) , 2 <= i <= n

F(n) - 回答

C ++实现:

int GetMaximumSubarraySum(const vector<int>& a)
{
    // note that vector a have 1-based index
    vector<int> v(a.size());
    v[0] = 0;
    v[1] = a[1];
    for(int i =2; i < a.size(); i++)
        v[i] = max(v[i-2] + a[i], v[i-1]);

    return v.back();
}

<强>解释

首先,主要想法是使用dynamic programming。 我们尝试使用具有N-1N-2第一元素的数组的已知答案来解决具有N元素的数组的任务。如果N = 0答案为0,而N = 1答案为A[1]。很明显。对于N >= 2,我们有两种不同的方式:

  1. 使用元素A[N],然后答案是A[N] + F[N-2](因为我们不能使用A [N-1]元素而F[N-2]是子数组1..N-2的最佳解决方案1}},我们不关心是否使用F[N-2]元素,这只是子阵列1..N-2的最佳解决方案。

  2. 不要使用元素A[N],那么答案是F[N-1](因为我们可以使用A [N-1]元素而F[N-1]是子阵列的最佳解决方案1..N-1,我们也不关心是否使用F[N-1]元素。

  3. 所以我们需要在这两种情况中获得最大值。 要解决此任务,您需要按递增顺序计算F[N]并记住答案。

    让我们看一下你的例子:

    [12, 8, 9, 10]

    F[0] = 0

    F[1] = 12 - 使用第一元素

    F[2] = max(F[0]+A[2], F[1]) = max(8, 12) = 12 - 使用第一元素

    F[3] = max(F[1]+A[3], F[2]) = max(21, 12) = 21 - 使用1-st,3-rd元素

    F[4] = max(F[2]+A[4], F[3]) = max(22, 21) = 22 - 使用第1,第4个元素

    答案是F[4] = 22

答案 1 :(得分:2)

我所知道的唯一一致成功的思考过程就是以前见过这个问题。看看你的问题,我的第一个想法是“我需要最大化一个总和,看似是一组相当简单的布尔约束”。在Knuth第4A卷第7.1.4节算法B Knuth描述了如何解决这样的问题,只要约束可以表示为可管理大小的http://en.wikipedia.org/wiki/Binary_decision_diagram。如果您已经有了BDD软件包,那么只需构建描述特定约束的BDD,就可以解决这类问题。

我的第二个想法是注意稍后在同一部分中,Knuth显示了BDD与布尔逻辑的线性网络之间的连接。鉴于此,应该有一个易于处理的动态编程解决方案来解决您的问题。如果您正在寻找一种通用的学习方法,动态编程是一个非常好的选择。在这种情况下,它似乎导致一种算法非常类似于Ivan Benko所呈现的算法,尽管他似乎在假设下工作 - 由您的示例数据支持 - 整数都是&gt; = 0,并且它可以用于一般整数,还有一些if语句。

答案 2 :(得分:0)

递归思考: 最好的结果是最大的情况 - 使用第一个元素(第一个在递归分支中)或不使用它总和

  

Best(i)= Max(A [i] + Best(i + 2),Best(i + 1))

答案 3 :(得分:0)

这是一个解决方案,称为kadane的Alogithme

Algorithm 1 Kadane’s algorithm
   M ← 0, t ← 0
   i ← 1
   for j ← 1 to n do          
      t ← t + a[j]
      if t > M then M ← t, (x1 , x2 ) ← (i, j)           
      if t ≤ 0 then t ← 0, i ← j + 1// reset the accumulation
   end for
   output M , (x1 , x2 )