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

题目:输入一个整型数组,数组里面有正数也有负数,数组中的连续一个或者多个整数组成一个子数组,每一个子数组都有一个和,求所有子数组和的最大值。要求时间复杂度为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。基于这种思路我们可以写出如下的代码:

1 #include

2 #include

3 using namespace std;

4

5 bool FindMaxSubarray(int *pArray,int arrayLength,int &largestSum)

6 {

7 //无效输入,返回false8 if(pArray == NULL || arrayLength <= 0)

9 return false;

10

11 int curSum = 0;

12 largestSum = 0;

13 for(int i = 0;i < arrayLength;++i)

14 {

15 curSum += pArray[i];

16

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

19 curSum = 0;

20

21 //找到更大的和,用largestSum保存22 if(curSum > largestSum)

23 largestSum = curSum;

24 }

25

26 //如果所有的数为都是小于等于0,找到该数组最大的数27 if(largestSum == 0)

28 {

29 largestSum = pArray[0];

30 for(int i = 1;i < arrayLength;++i)

31 {

32 if(pArray[i] > largestSum)

33 largestSum = pArray[i];

34 }

35 }

36

37 return true;

38 }

39

40 int main()

41 {

42 cout<

43 int n;

44 cin>>n;

45

46 cout<

47 int *p = new int[n];

48 for(int k = 0;k < n;++k)

49 {

50 cin>>p[k];

51 }

52

53 cout<

54 for(k = 0; k < n;++k)

55 cout<

56

57 cout<

58 cout<

59 int saveSum;

60 FindMaxSubarray(p,n,saveSum);

61 cout<

62

63 return 0;

64 }

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

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

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

References:

注:

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

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值