LeetCode/乘积最大的子数组
给你一个整数数组 nums ,请你找出数组中乘积最大的非空连续子数组(该子数组中至少包含一个数字),并返回该子数组所对应的乘积。
经典子数组题目,使用动态规划,这里需要注意状态的转移,一般来说,
子数组题目状态转移在于把当前元素加入前面的连续子数组形成新的连续子数组
或者本身作为新的子数组两种选择,所以dp[i]定义为以i结尾的连续子数组对应值,方便状态转移
值得一提的是,这里需要使用两个dp表,因为最大值也可能是由最小值转换过来的
1. 动态规划
class Solution {
public:
int maxProduct(vector<int>& nums) {
vector <int> maxF(nums), minF(nums);
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]));//三者取最小
}
return *max_element(maxF.begin(), maxF.end());
}
};
2. 动态规划一维优化
由于两个数组都是对上一个状态的转移,这里还要暂且记录一下上一个状态,防止更新后丢失
class Solution {
public:
int maxProduct(vector<int>& nums) {
int maxF = nums[0], minF = nums[0], ans = nums[0];//长度最小为1,所以取第一个
for (int i = 1; i < nums.size(); ++i) {//从第二个数开始
int mx = maxF, mn = minF;//这里需要暂时记录一下用于minF的计算
maxF = max(mx * nums[i], max(nums[i], mn * nums[i]));
minF = min(mn * nums[i], min(nums[i], mx * nums[i]));
ans = max(maxF, ans);//更新结果
}
return ans;
}
};
3. 动态规划(最终优化)
通过交换,减少了求取最值的操作
class Solution {
public:
int maxProduct(vector<int>& nums) {
int max_ = INT_MIN, imax = 1, imin = 1;//保证第一个值运算后得到原来值
for(int i=0; i<nums.size(); i++){//从第一个数开始
if(nums[i] < 0) swap(imax,imin);
imax = max(imax*nums[i], nums[i]);
imin = min(imin*nums[i], nums[i]);
max_ = max(max_, imax);
}
return max_;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了