原题如下:
给定一个整数数组 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】为负数)即qnums【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;
}