您的位置:首页 > 其它

【算法07】求子数组的最大和

2011-11-30 14:38 239 查看
  题目:输入一个整型数组,数组里面有正数也有负数,数组中的连续一个或者多个整数组成一个子数组,每一个子数组都有一个和,求所有子数组和的最大值。要求时间复杂度为O(n)。

  例如:输入数组为{1,-2,3,10,-4,7,2,-5},和的最大子数组为{3,10,-4,7,2},因此输出为子数组的和18。

  分析1:一般地,对于在整体集合内寻找满足某一条件子集合问题,最直观也最后理解的方法就是——枚举,求出所有子数组的和,然后比较求出最大的值,即可。然而对于长度为n的数组,它的子数组共有n(n-1)/2个,O(n^2),然后再对于每一个数组求和,时间复杂度为O(n)。因此总的时间复杂度为O(n^3)。效率太低。

  分析2:我们知道,对于某个子数组,如果它的下一个数为正数,加上该正数和会增加;而加上一个负数,和会减少;如果当前子数组的话为负数,下一个数不论是正数还是负数,都会使得子数组的和进一步减少,因而这时候应该将子数组和重置为0。基于这种思路我们可以写出如下的代码:

#include<iostream>
#include<string>
using namespace std;

bool FindMaxSubarray(int *pArray,int arrayLength,int &largestSum)
{
//无效输入,返回false
if(pArray == NULL || arrayLength <= 0)
return false;

int curSum = 0;
largestSum = 0;
for(int i = 0;i < arrayLength;++i)
{
curSum += pArray[i];

//如果当前和小于0,重置为0
if(curSum < 0)
curSum = 0;

//找到更大的和,用largestSum保存
if(curSum > largestSum)
largestSum = curSum;
}

//如果所有的数为都是小于等于0,找到该数组最大的数
if(largestSum == 0)
{
largestSum = pArray[0];
for(int i = 1;i < arrayLength;++i)
{
if(pArray[i] > largestSum)
largestSum = pArray[i];
}
}

return true;
}

int main()
{
cout<<"Enter the length of your array:"<<endl;
int n;
cin>>n;

cout<<"Enter the numbers in your array:"<<endl;
int *p = new int
;
for(int k = 0;k < n;++k)
{
cin>>p[k];
}

cout<<"your array is:"<<endl;
for(k = 0; k < n;++k)
cout<<p[k]<<" ";

cout<<endl;
cout<<"the largest subarray sum is:"<<endl;
int saveSum;
FindMaxSubarray(p,n,saveSum);
cout<<saveSum<<endl;

return 0;
}


  关于上述代码有两点需要注意:

  (1)如果一个数组中的数全部都是负数,那么这时候largestSum还是初始值0,而这时候整个数组的子数组和的最大值就是数组中的最大元素,因而单独拿出来考虑。

  (2)关于函数的返回类型,如果按照正常的考虑,函数的返回值应该为整型,即范围子数组和的最大值,然而这样存在一个问题,如果输入本身的无效值,返回什么?返回0,那么如果数组中有0元素,其余全是负数元素,这时候0代表无效输入还是最大值?返回-1?数组中的最大元素真的是-1,怎么办?综上考虑,把子数组和的最大值以引用的方式传入函数的参数,同时让函数范围一个处理正常与否的标志,应该是比较好的方式(何海涛博主的考虑方式很严谨。)

References:

何海涛博客:http://zhedahht.blog.163.com/blog/static/254111742007219147591/

注:

1)本博客所有的代码环境编译均为win7+VC6。所有代码均经过博主上机调试。

2)博主python27对本博客文章享有版权,网络转载请注明出处http://www.cnblogs.com/python27/。对解题思路有任何建议,欢迎在评论中告知。

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: