最大连续积。刘汝佳的算法竞赛入门经典提供了一个简单的O(n^2) 的方法,但通过分治,可以把最大连续积降到O(n*logn)。代码如下
#include<iostream>
#include<stdio.h>
using namespace std;
int n, num[20];
long long dc(int a, int b){
//只有一个元素的时候,返回这个元素
if(b-a==1)
return num[a];
//划分
int mid = a+(b-a)/2;
//递归
long long va = dc(a, mid);
long long vb = dc(mid, b);
long long vm = max(va, vb);
//合并
long long aa=num[mid-1], bb=num[mid];
long long am=aa, bm=bb;
//从分界点左端(不含,-1)开始找最大积, 最小积(考虑负数情况)
long long v=1, w=1;
for(int i=mid-1; i>=a; i--){
aa = max(aa, v*=num[i]);
am = min(am, w*=num[i]);
}
//从分界点右端(含)开始找最大积, 最小积(考虑负数情况)
v=1, w=1;
for(int i=mid; i<b; i++){
bb = max(bb, v*=num[i]);
bm = min(bm, w*=num[i]);
}
//aa bb 为最大值的时候, am,bm考虑可能是负数的情况
long long ret = max(aa*bb, am*bm);
return max(ret, vm);
}
int main(){
int kase=0;
while(cin >> n){
kase++;
for(int i=0; i<n; i++){
cin >> num[i];
}
long long ans = dc(0, n);
if(ans<0) ans=0;
printf("Case #%d: The maximum product is %lld.\n\n", kase, ans);
}
return 0;
}
但是,还有O(n)的算法
#include<iostream>
#include<stdio.h>
using namespace std;
int n, num[20];
int main(){
long long v, maxs;
int kase=0;
while(cin >> n){
kase++;
maxs = 0;
for(int i=0; i<n; i++){
cin >> num[i];
}
//v 记录当前乘积
v = 1;
for(int i=0; i<n; i++){
//如果之前累计的乘积使得绝对值减少,则放弃前面累积的乘积
if(v<1 && v>-1)
v = num[i];
else
v *= num[i];
maxs = max(maxs, v);
}
//最后面得到的v肯定是绝对值最大的,但得到的maxs却不一定是最大的
//反向再过一遍,因为可能因为负数,而错过最大值
v = 1;
for(int i=n-1; i>=0; i--){
if(v<1 && v>-1)
v = num[i];
else
v *= num[i];
maxs = max(maxs, v);
}
printf("Case #%d: The maximum product is %lld.\n\n", kase, maxs);
}
return 0;
}