LeetCode第152题.乘积最大子序列

本文探讨了在给定整数数组中找到乘积最大的连续子序列问题,通过分析不同情况,提出了一种动态规划解决方案,包括记录最大值、最小值和当前位置值,以应对正负数变化带来的挑战。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原题如下:

给定一个整数数组 nums ,找出一个序列中乘积最大的连续子序列(该序列至少包含一个数)。

示例 1:

输入: [2,3,-2,4]
输出: 6
解释: 子数组 [2,3] 有最大乘积 6。
示例 2:

输入: [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。

分析:

nums【i-1】 必然会得到一个 max值,,,那么我们能不能通过nums【i-1】求得nums【i】呢,,测试 一些 数据 就知道了
比如 对于 -2,4,-3 而言, nums【1】的 max值 是4,而nums【2】的max值却是 -24-3 为 24,== 所以可以得到结论,从i-1的max值是不能直接推出i的max值的(即我们还需要记录其他的辅助值!!!!)==

那么还需要的辅助变量是什么确实是比较耐人寻味的!!!

这个 需要从目的出发来分析,如果求 i的max值有哪几种情况呢???
1)max值就是 nums【i】(这种情况别忘了)
2)max值是从i-1的max值继承而来的
3)max值为除了i当前外 ,之前元素连乘获得的最大乘积 p乘以nums【i】 (ps:nums【i】为正数)即p nums【i】
4)max值为除了i当前外 ,之前元素连乘获得的最小乘积q乘以nums【i】 (ps:nums【i】为负数)即q
nums【i】

综上所述对于一个i位置我们需要记录三样东西:

1)当前位置的max值

2)包含当前位置的最大连乘值(指向0位置方向的)

3)包含当前位置的最小连乘值(指向0位置方向的)

代码如下(注意lz为了方便理解,开了一个vector记录了每个位置下的上述3个数据,实际只需要3个int 记录即可)

struct My_node{
	int max_elem;
	int and_this_max;
	int and_this_min;
};
    int max_three_nums(int &x,int &y,int &z){
		int tmp = max(x, y);
		tmp = max(tmp, z);
		return tmp;
	}
	int min_three_nums(int &x, int &y, int &z){
		int tmp = min(x, y);
		tmp = min(tmp, z);
		return tmp;
	}
	int maxProduct(vector<int>& nums) {
		if (nums.size() == 1)return nums[0];
		vector<My_node>m(nums.size());
		m[0].max_elem = nums[0]; m[0].and_this_max = nums[0]; m[0].and_this_min = nums[0];
		for (int i = 1; i <= nums.size() - 1; i++){
			int x = m[i - 1].max_elem;
			int y = m[i - 1].and_this_max*nums[i];
			int z = m[i - 1].and_this_min*nums[i];
			m[i].max_elem = max( max_three_nums(x,y,z),nums[i]);
			m[i].and_this_max = max_three_nums(y, z, nums[i]);
			m[i].and_this_min = min_three_nums(y, z, nums[i]);
		}
		return m[nums.size() - 1].max_elem;
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值