题目地址:https://leetcode-cn.com/problems/maximum-product-subarray/
文章目录- LeetCode-152. 乘积最大子数组(中等)
- 1. 题目描述及示例
- 示例一:
- 示例二:
- 2. 题解和代码实现
- 2.1 初始化
- 2.2 状态转移方程
- 代码实现(C++ 2022-4-8)
- 3. 总结
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
测试用例的答案是一个 32-位 整数。
子数组 是数组的连续子序列。
示例二:输入: nums = [2,3,-2,4]
输出: 6
解释:子数组 [2,3] 有最大乘积 6。
2. 题解和代码实现输入: nums = [-2,0,-1]
输出: 0
解释: 结果不能为 2, 因为 [-2,-1] 不是子数组。
采用最大子序和的经验53.最大子数组和 ,我们可以进行定义 :
max_results = max(max_results*nums[i]),nums[i])
但是如果遇到[-2,3,4,-5,6],会发现按照上式所得到的结果是{-2,3,12,-5,6} 那么最终的最大结果是12,显然不是我们想要的,也就是我们想要的结果:当前位置的最优解未必是由前一位置的最优解转移得到的。
所以,在这里可以进行分为正类的负类如果当前位置是一个正数,我们希望他的前一位置结尾的某个段的积是正数,并且希望它越大越好如果当前位置是一个负数, 我们希望他的前一位置结尾的某个段的积是负数,并且希望它越小越好。采用maxF来进行表示正类,minF来进行表示负类。即:
- 所以最大值,应该是 :
max{maxF[i-1]*nums[i],minF[i-1]*nums[i],nums[i]}
- 所以最大值,应该是 :
min{maxF[i-1]*nums[i],minF[i-1]*nums[i],nums[i]}
2.1 初始化
在这里进行初始化:利用 max_result 来进行存储最终的最大值,用 maxF 和 minF 分别来进行存储正类和负类。
int max_result = nums[0],maxF = nums[0],minF = nums[0];
2.2 状态转移方程
在这里的每一步更新需要用到前一步的结果,所以首先进行前一步结果的保存。
int mx = maxF,mi = minF;
maxF = max(mx*nums[i],max(mi*nums[i],nums[i]));
minF = min(mi*nums[i],min(mx*nums[i],nums[i]));
代码实现(C++ 2022-4-8)
class Solution {
public:
int maxProduct(vector<int>& nums) {
// 优化空间
int max_result = nums[0],maxF = nums[0],minF = nums[0];
// int max_result = maxF = minF = nums[0];
for(int i=1;i<nums.size();i++){
int mx = maxF,mi = minF;
maxF = max(mx*nums[i],max(mi*nums[i],nums[i]));
minF = min(mi*nums[i],min(mx*nums[i],nums[i]));
max_result = max(max_result,maxF);
}
// vector maxF(nums.size(),0), minF(nums.size(),0);
// maxF[0] = minF[0] = nums[0];
// int max_result = maxF[0];
// for (int i = 1; i < nums.size(); ++i) {
// maxF[i] = max(maxF[i - 1] * nums[i], max(nums[i], minF[i - 1] * nums[i]));
// minF[i] = min(minF[i - 1] * nums[i], min(nums[i], maxF[i - 1] * nums[i]));
// max_result = max(maxF[i],max_result);
// }
return max_result;
}
};
3. 总结
尽管利用动态规划求解,注意当前位置的最优解未必是由前一位置的最优解转移得到的 这一情况,要进行合理的分析。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)