题解 | #子数组最大乘积#

子数组最大乘积

http://www.nowcoder.com/practice/9c158345c867466293fc413cff570356

子数组最大乘积(贪心)

题意

一个有正负和零的double数组中,最大的子数组乘积为多少

思路分析

快速运算乘积

如果数组中没有零

计算数组一段的乘积,相当于计算从数组起始到结束的乘积,除以起始到数组开始之前的积

f(i,j) = premul[j] / premul[i-1]

局部最优

alt

对于选中的结束位置j,我们要让f(i,j) 尽量大,则premul[i-1]的绝对值尽量小,且和它同号。

如果一正一负,取正值即可,不会发生运算。

零值

如果有零,零相当于把数组的分界线,只要乘积跨越了零始终是零,所以只用考虑被零值划分出的一个个小数组

状态维护

按符号不同分别维护,同符号的绝对值最小值

if(cur > 0){
    minpos = min(minpos, cur);
}else if(cur < 0){
    maxneg = maxneg == 1? cur : max(maxneg, cur);
}

记录答案

每次用 当前值 除以 和它同号的最小绝对值的值

ans = max(ans, cur/同号绝对值最小的)

题解

把上面的联系起来

class Solution {
public:
    double maxProduct(vector<double> arr) {
        if(arr.size() == 0)return 0;
        double ans = arr[0];
        double minpos = 1; // 最小正绝对值
        double maxneg = 1; // 最小负绝对值
        double cur = 1;
        for(auto v: arr){
            cur *= v;
            if(v == 0){ // 零值
                ans = max(ans,(double)0);
                cur = 1;
                minpos = maxneg = 1;
            }else if(cur > 0){ // 正
                ans = max(ans, cur / minpos);
                minpos = min(minpos, cur);
            }else if(cur < 0){ // 负
                ans = max(ans, cur / maxneg);
                maxneg = maxneg == 1? cur : max(maxneg, cur);
            }
        }
        return ans;
    }
};

复杂度分析

时间复杂度: 遍历数组操作,每个位置时间复杂度为常数,所以总时间复杂度为O(n)O(n)

空间复杂度: 只用了常数个额外变量,所以空间复杂度为O(1)O(1)

全部评论

相关推荐

把实习生当正职使昨天第一天就加班,晚上连口饭都没吃上,以后日子咋过,我不想干了
码农索隆:实习不怕忙,就怕干的活重复且没难度,要干就干那种有深度有难度的任务,这样才能快速的提升
点赞 评论 收藏
分享
05-19 15:21
已编辑
华南农业大学 Java
白火同学:你才沟通了200,说实话,北上广深杭这里面你连一座城市的互联网公司都没投满呢,更别说还有各种准一线二线城市了。等你沟通突破了三位数,还没结果再考虑转行的事吧。
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务