求最大子序列乘积

数据结构与算法分析——c语言描述 练习2.12(c) 答案

        这道题有两个难点,第一是需要考虑值为0的时候,第二是需要考虑值为负的时候.

        说下我的思路,用联机算法,只需要从头到尾遍历一遍就行了.

        第一个问题很好解决,每次遇到值为0的时候,就分成一段,算出这一段的最大子序列乘积,输出答案时只需要比较每一段的最大值就好了.

        第二个问题可以拆成当这一段有偶数个负数和有奇数个负数这两种情况.有偶数个负数时可以不用管,因为这一段中的所有数相乘的结果必然是最大的.而奇数个负数可以拆成偶数个负数加上一个负数,再复杂的情况也能化简为"a,b","b,a","a,b,a"这三种情况(a代指正数,b代指负数).因此将每一段拆成三部分,开头的部分到第一个负值结束(注意:包含第一个负值),结尾的部分从最后一个负值开始(注意:包含最后一个负值).

        从头开始遍历的时候,将一段中的每个数字都累乘起来,这个乘积如果除以开头部分的所有乘积就是后半部分,这个乘积如果除以结尾部分的所有乘积就是前半部分,比较一下就是答案了.

        当每一段只有一个值的时候也需要注意一下,因为不加特殊限制,负值会被运算成1.

#include <iostream>
#include <cmath>
#include <vector>
using namespace std;
int MaxM(vector<int>&nums) {
	int Spart = 1, Endpart = 1,f_max=0,t=0,Fmax=INT_MIN,start=0,all=1;
    for (int i = 0; i <= nums.size(); i++) {
        if (i==nums.size()||nums[i] == 0) {
            if (i!=nums.size()&&nums[i]==0) Fmax=max(0,Fmax);
            if (i-start<=1){
                if (start==nums.size()) break;
                Fmax=max(Fmax,nums[start]);
            } 
			else if (all>0) Fmax=max(Fmax,all);
			else if (all<0) Fmax = max(Fmax,max(all / Spart, all / Endpart));
			t = 0,Spart = 1,Endpart = 1,f_max = 0,all = 1,start=i+1;
			continue;
        }
		all *= nums[i];
		if (t == 0) Spart *= nums[i];
		if (nums[i] < 0) {
	        t = 1;
			Endpart = nums[i];
		}
	    if (nums[i] > 0 && t == 1) Endpart *= nums[i];
	}
    return Fmax;
}
int main() {
	int num;
	vector<int>nums;
	while (scanf("%d", &num)) nums.push_back(num);
	int MaxProduct=MaxM(nums);
	cout << MaxProduct << endl;
	return 0;
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值