栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

求最大子序列乘积

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

求最大子序列乘积

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

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

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

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

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

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

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

#include 
#include 
#include 
using namespace std;
int MaxM(vector&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;
	vectornums;
	while (scanf("%d", &num)) nums.push_back(num);
	int MaxProduct=MaxM(nums);
	cout << MaxProduct << endl;
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1034188.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号