经典题算法笔记:求最大子数组和

来源:互联网 发布:时序数据库应用场景 编辑:程序博客网 时间:2024/06/05 08:39
一、题目描述

给定一个数组a[0,...,n-1],求其最大子数组(长度>=1)和(子数组下标须连续)

输入描述:第一行一个整数n(1<=n<=5000),然后依次输入n个整数(每个整数范围[-5000, 5000])。输出描述:输出一个整数表示最大子数组和


二、​暴力做法

思路十分直接。 ​可先固定起点也可先固定长度,枚举出所有子数组的和。但时间复杂度太高,容易超时。

我的C++代码:

#include "stdafx.h"

#include

using namespace std;

int main()

{   

int n;  

 cin >> n;  

 int arr[5000];

for (int i = 0; i < n; i++)       

cin >> arr[i];    int max = 0;

  int sum(int i, int j, int*p);   

for (int i = 0; i < n; i++)     

  for (int j = i; j < n; j++)         

  if(max

 cout << max << endl;  

 return 0;

}

 

int sum(int i, int j, int*p)

{  

 int ans = 0;  

 for (int k = i; k <= j; k++)       

ans = ans + *(p + k);  

 return ans;

}

三、动态规划做法

这种做法极大降低了时间复杂度,有效避免了很多重复计算。基本思路如下:

1.把问题变成一个递推问题​,把原本是一个整体的大数组看作是由短数组递推而来的长数组。短数组的所有计算结果可以为长数组所用。

2.动态规划的思维:无后效性——前一部分如何选择对后面的选择无任何影响;最优化原理——子问题最优解导致全局最优解

3.具体做法:原问题=>在数组的n位置求a[0]到a[n]数组的最大子数组和​=>在数组的i位置求a[0]到a[i]数组的最大子数组和,记为max[i]=>记包含a[i]的最大子数组和为CurMax[i]。若CurMax[i-1]>0那么CurMax[i]=CurMax[i-1]+a[i];(下标必须连续,又要含有a[i],所以一定含有a[i-1]),否则CurMax[i]=a[i];注意到max[i]的计算只需比较两种情况的优劣:1)含有a[i],即为CurMax[i];2)不含a[i],即为max[i-1],选择二者中较大的赋给max[i]  =>一路递推下去,到a[0]时,max[0]=a[0],CurMax[0]=a[0],完成递推

我的C++代码如下:

// lab060102.cpp : 定义控制台应用程序的入口点。

//#include "stdafx.h"

#include

using namespace std;

int main()

{  

 int arr[5000];

  int CurMax[5000], max[5000];  

 int n;  

 cin >> n;  

 int i;  

 for (i = 0; i < n; i++)    

   cin >> arr[i];   

CurMax[0] = arr[0];

max[0] = arr[0];  

 for (i = 1; i < n; i++)

  {    

   if (CurMax[i - 1] > 0) CurMax[i] = CurMax[i - 1] + arr[i]; else CurMax[i] = arr[i];        if (CurMax[i]>max[i - 1]) max[i] = CurMax[i]; else max[i] = max[i - 1];  

 }

   cout << max[n - 1] << endl;   

return 0;

}

​​

0 0
原创粉丝点击