求连续子数组的最大和与最大积

本文介绍了一种求解数组中连续子数组最大和的问题,并提供两种算法实现:一种时间复杂度为O(n^3),另一种更高效的算法时间复杂度为O(n)。此外,还探讨了如何求解最大连续子段的乘积问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

第一节、求子数组的最大和

 

题目描述:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)。

 

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
思路一:求一个数组的最大子数组和,如此序列1, -2, 3, 10, -4, 7, 2, -5,我想最最直观也是最野蛮的办法便是,三个for循环三层遍历,求出数组中每一个子数组的和,最终求出这些子数组的最大的一个值。记Sum[i, …, j]为数组A中第i个元素到第j个元素的和(其中0 <= i <= j < n),遍历所有可能的Sum[i, …, j],那么时间复杂度为O(N^3)。
代码如下:

 

 

例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,那么最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18。
所有的东西都在以下两行,即:
b  :  0  1  -1  3  13   9  16  18  13  
sum:  0  1   1  3  13  13  16  18  18
其实算法很简单,当前面的几个数,加起来后,b<0后,把b重新赋值,置为下一个元素,b=a[i]。当b>sum,则更新sum=b;若b<sum,则sum保持原值,不更新.
代码如下:

 

[cpp] view plaincopy

  1. #include <iostream.h>  
  2. using namespace std;  
  3.   
  4. int maxSum(int* a, int n)  
  5. {  
  6.     int sum=a[0];  
  7.     int b=0;  
  8.       
  9.     for(int i=0; i<n; i++)  
  10.     {  
  11.         if(b<0)             
  12.             b=a[i];  
  13.         else  
  14.             b+=a[i];  
  15.         if(sum<b)  
  16.             sum=b;  
  17.     }  
  18.     return sum;  
  19. }  
  20.   
  21. int main()  
  22. {  
  23.     int a[10]={1, -2, 3, 10, -4, 7, 2, -5};  
  24.     cout<<maxSum(a,8)<<endl;  
  25.     return 0;  

算法 2

  1. //Algorithm 1:时间效率为O(n*n*n)  
  2. int MaxSubsequenceSum1(const int A[],int N)  
  3. {  
  4.     int ThisSum=0 ,MaxSum=0,i,j,k;  
  5.     for(i=0;i<N;i++)  
  6.         for(j=i;j<N;j++)  
  7.         {  
  8.             ThisSum=0;  
  9.             for(k=i;k<j;k++)  
  10.                 ThisSum+=A[k];  
  11.               
  12.             if(ThisSum>MaxSum)  
  13.                 MaxSum=ThisSum;  
  14.         }  
  15.         return MaxSum;  
  16. }  
  17.  

 

给定一个整型数足a,求出最大连续子段的乘积,比如 1, 2, -8, 12, 7则输出12 * 7 = 84

 

代码如下:

[html] view plaincopy

  1. // maxProduct.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <iostream>  
  6. #include   <stdlib.h>   
  7. #include   <stdio.h>   
  8. using namespace  std;  
  9.   
  10.   
  11.   
  12. // 子数组的最大乘积  
  13. int MaxProduct(int *a, int n)  
  14. {  
  15.     int maxProduct = 1; // max positive product at current position  
  16.     int minProduct = 1; // min negative product at current position  
  17.     int r = 1; // result, max multiplication totally  
  18.   
  19.     for (int i = 0; i < n; i++)  
  20.     {  
  21.         if (a[i] > 0)  
  22.         {  
  23.             maxProduct *= a[i];  
  24.             minProduct = min(minProduct * a[i], 1);  
  25.         }  
  26.         else if (a[i] == 0)  
  27.         {  
  28.             maxProduct = 1;  
  29.             minProduct = 1;  
  30.         }  
  31.         else // a[i] < 0  
  32.         {  
  33.             int temp = maxProduct;  
  34.             maxProduct = max(minProduct * a[i], 1);  
  35.             minProduct = temp * a[i];  
  36.         }  
  37.   
  38.         r = max(r, maxProduct);  
  39.     }  
  40.   
  41.     return r;  
  42. }  
  43.   
  44. int _tmain(int argc, _TCHAR* argv[])  
  45. {  
  46.     int a[]={1, -2, -3,0,5};  
  47.     int result = MaxProduct(a,5);  
  48.     cout<<result<<endl;  
  49.     system("pause");  
  50.     return 0;  
  51. }  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值