UVA 11059 - Maximum Product

最大连续积。刘汝佳的算法竞赛入门经典提供了一个简单的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;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值