分析一个问题:
最大连续和的问题。给出长度为n序列A1,A2,...An求连续最大和;
对于一般的想法,可以给出下面的代码
t = 0;
best = A[1];
for(int i = 1; i <= n; i++)
for(int j = i ; j <= n; j++)
{
int sum = 0;
for ( int k = i ; k <= j; k++)
{
sum += A[K]; t++:
}
if(sum > best) best = sum;//更新最大值
}
采用的思想:幼儿园学生思想!!!!
由于进行了三重循环,时间复杂度为N的三次方
对于推算时间复杂度:
()采取上界分析,最坏的情况是什么情况?对于三重循环最多也就是每个循环都进行N次,于是就推算出时间复杂度 T(n) = O(n^3);
在这种情况下,你一定要试着优化你的算法
于是我们可以使用一些优化:
S[0] = 0;
for(int i = 1; i <=n; i+) s[i] = s[i-1] +A[i];//推进前缀
for(int i = 1; i <=n; i++)
for(int j =i; j <= n; j++) best = max(best ,s[j] - s[i-1]);
采用的思想:递推的思想!!!(初中生必备)
这样就可以进行一个一重循环+一个二重循环
()采用上界分析,最坏的情况也就是时间复杂度T(n) = O(n^2)
----------------------------------------------------------------------------------------------------------------------------------------------------(难度增加分割线)
使用分治法来解决问题
(1) 划分问题 : 把问题的实例划分成子问题
(2)递归求解 : 递归解决子问题
(3)合并问题 : 合并子问题得到原问题的解
划分:把序列中的元素分成元素数量尽量可能相等的两半;
递归求解:分别求出位于左半或者位于右半的最佳序列
合并:求出起点位于左半、终点位于右半的的最大连续序列,并和子问题的最优解比较
#include<bits/stdc++.h>
using namespace std;
int maxsum(int *s, int x, int y)
{
int v,left,right,mmax;
if(y - x == 1)
{
return s[x];
}
int m = x +(y - x) /2;//尽可能中间的数
mmax = max(maxsum(s,x,m),maxsum(s,m,y));//递归求解
v = 0;
left = s[m-1];
for(int i = m-1 ; i>= x; i--)
{
left = max(left,v += s[i]);
}
v = 0;
right = s[m];
for(int i = m; i < y; i++)
{
right = max(right, v += s[i]);
}
return max(mmax,left+right);//感觉向前走???
}
int main()
{
int n;
int s[10000];
cin>>n;
for(int i = 0 ;i < n; i++)
{
cin>>s[i];
}
int m;
m = maxsum(s,0,n);
cout<<m<<endl;
return 0;
}
递归求解思想(大学生正常思维)
附上全代码!感觉就像切水出波一样,在每次切完的中间再切 这样求解时间复杂度T(n) = O(n*logn)
附上全代码!感觉就像切水出波一样,在每次切完的中间再切 这样求解时间复杂度T(n) = O(n*logn)