编程之好2.14 求数组的子数组之和的最大值
编程之美2.14 求数组的子数组之和的最大值
通过 if(nStart > nAll) 可以确定端点k, 获取nAll后从端点k顺序相加直到和等于nAll 还是O(n)
通过 if(nStart > nAll) 可以确定端点k, 获取nAll后从端点k顺序相加直到和等于nAll 还是O(n)
要位置的话仍然是O(n)啊。。。
一个有N个整数元素的一维数组( A[0], A[1], ... , A[n-2], A[n-1]),子数组之和的最大值是什么?(要求子数组的元素是连续的)
例子:有数组( -2, 5, 3, -6, 4, -8, 6),则其子数组之和的最大值为8,其对应的数组为(5,3)
《编程之美》最后给出了一个时间复杂度为O(n)的算法,实现的代码如下:
#include <stdio.h> int maxSubSum(int* array, int length) { int nAll = array[length -1]; int nStart = array[length-1]; int i; for( i = length-2; i>=0; i--) { if(nStart < 0) nStart = 0; nStart += array[i]; if(nStart > nAll) //若当前子数组之和大于nAll,则更新nAll nAll = nStart; } return nAll; } int main() { int a[7] = {-2,5,3,-6,4,-8,6}; int maxSub = maxSubSum(a,7); printf("Max sub sum = %d\n",maxSub); }
其中nAll保存当前的最大子数组之和,先定义初值为最后一个元素,
nStart保存当前的子数组之和,若为负数(最大和的子数组不可能包含当前子数组),则在下次遍历时清零,重新寻找最大和的子数组
1 楼
seedjyh
2011-05-13
<p>典型的DP</p>
<p>计算从最左端到当前位置中最大和以及最小和,两者数列的右端点就是答案了~</p>
<p>计算从最左端到当前位置中最大和以及最小和,两者数列的右端点就是答案了~</p>
2 楼
Hmily49
2011-05-29
<div class="quote_title">seedjyh 写道</div><div class="quote_div"><p>典型的DP</p>
<p>计算从最左端到当前位置中最大和以及最小和,两者数列的右端点就是答案了~</p></div><br/>可以说详细点么?
<p>计算从最左端到当前位置中最大和以及最小和,两者数列的右端点就是答案了~</p></div><br/>可以说详细点么?
3 楼
chriszeng87
2011-05-29
<div class="quote_title">Hmily49 写道</div>
<div class="quote_div">
<div class="quote_title">seedjyh 写道</div>
<div class="quote_div">
<p>典型的DP</p>
<p>计算从最左端到当前位置中最大和以及最小和,两者数列的右端点就是答案了~</p>
</div>
<br>可以说详细点么?</div>
<p>同问</p>
<div class="quote_div">
<div class="quote_title">seedjyh 写道</div>
<div class="quote_div">
<p>典型的DP</p>
<p>计算从最左端到当前位置中最大和以及最小和,两者数列的右端点就是答案了~</p>
</div>
<br>可以说详细点么?</div>
<p>同问</p>
4 楼
minipenguin
2011-06-03
动态规划,从数组的一端开始遍历,遇到负数则置0,否则求和,遍历完答案就出来了
5 楼
david.org
2011-06-21
楼主正解,不过这题要是要求记录数组位置的话,估计就做不到 O(N) 的时间复杂度了
6 楼
lagrangee
2012-03-30
david.org 写道
楼主正解,不过这题要是要求记录数组位置的话,估计就做不到 O(N) 的时间复杂度了
通过 if(nStart > nAll) 可以确定端点k, 获取nAll后从端点k顺序相加直到和等于nAll 还是O(n)
7 楼
liguocai2009
2012-06-13
这一题有一个非常重要的前提。。。最小值是0。。。否则怎么想都是o(n*n)
8 楼
liguocai2009
2012-06-13
lagrangee 写道
david.org 写道
楼主正解,不过这题要是要求记录数组位置的话,估计就做不到 O(N) 的时间复杂度了
通过 if(nStart > nAll) 可以确定端点k, 获取nAll后从端点k顺序相加直到和等于nAll 还是O(n)
要位置的话仍然是O(n)啊。。。
9 楼
liguocai2009
2012-06-13
我搞错了。。。
这条题目我刚开始想的是知道a[0]..a[i]子数组的最大值,推导出a[0]...a[i+1]子数组最大值,推导的关键是判断下面3者谁是最大值,最大值的那个就是a[0]...a[i+1]的子数组最大值
a[0]...a[i]的子数组最大值 + a[i+1]
a[i+1]
a[ a[0]...a[i]的最大值子数组的起始index ] 到 a[i+1]的和
这个算法是 O(n*n)。
看了看博文,发现博文是利用了数学,轻松地解决了问题...思路上的根本差别是,我是想由n推出n+1,而博文是利用数学规律
if c>=0
a+c > a
else if c<0
a+c <a
这条题目我刚开始想的是知道a[0]..a[i]子数组的最大值,推导出a[0]...a[i+1]子数组最大值,推导的关键是判断下面3者谁是最大值,最大值的那个就是a[0]...a[i+1]的子数组最大值
a[0]...a[i]的子数组最大值 + a[i+1]
a[i+1]
a[ a[0]...a[i]的最大值子数组的起始index ] 到 a[i+1]的和
这个算法是 O(n*n)。
看了看博文,发现博文是利用了数学,轻松地解决了问题...思路上的根本差别是,我是想由n推出n+1,而博文是利用数学规律
if c>=0
a+c > a
else if c<0
a+c <a