给定一个整数数组,整数子集的最大总和是多少,这样子集中的整数最初并不是彼此相邻?
示例:
[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,我仍然有兴趣学习不同的方法。)
答案 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-1
和N-2
第一元素的数组的已知答案来解决具有N元素的数组的任务。如果N = 0
答案为0
,而N = 1
答案为A[1]
。很明显。对于N >= 2
,我们有两种不同的方式:
使用元素A[N],
然后答案是A[N] + F[N-2]
(因为我们不能使用A [N-1]元素而F[N-2]
是子数组1..N-2
的最佳解决方案1}},我们不关心是否使用F[N-2]
元素,这只是子阵列1..N-2
的最佳解决方案。
不要使用元素A[N]
,那么答案是F[N-1]
(因为我们可以使用A [N-1]元素而F[N-1]
是子阵列的最佳解决方案1..N-1
,我们也不关心是否使用F[N-1]
元素。
所以我们需要在这两种情况中获得最大值。
要解决此任务,您需要按递增顺序计算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 )