力扣-152-乘积最大的子数组
对于dp[i],
- 如果nums[i-1]>0,dp[i-1]也>0,那就是
dp[i-1]*nums[i-1]
- 如果<0,>0,那就是
nums[i-1]
-
0,<0,那就是
nums[i-1]
- <0,<0,那就是
dp[i-1]*nums[i-1]
同样参考最大子数和,还需要一个额外变量来记录最大的…
int maxProduct(vector<int>& nums) { int n = nums.size(),maxP = -11; vector<int> dp(n+1); dp[0] = 1; for (int i = 1; i <= n; i++) { int temp = nums[i - 1] * dp[i - 1]; if (temp > 0) dp[i] = temp; else dp[i] = nums[i - 1]; maxP = max(maxP, dp[i]); } return maxP; }
但是这么做是错误的,就比如-2,3,-4
这个例子,最后以-4结尾的子数组最大乘积是24,而不是-4
它参考的不是上一步的最优解3,而是-2和3的乘积-6,也就是说至少这么照搬定义是不符合“最优子结构”的
瞄了题解的提示
这样定义,关键在于对nums[i-1]正负性的讨论,
- 如果nums[i-1]>0,那么我们期望结果最大的话,就希望前面最大的正数乘积
- 如果nums[i-1]<0,那么就期望前面最小的负数乘积
int maxProduct(vector<int>& nums) { int n = nums.size(),maxP = -11; vector<int> dp(n+1),minRecord(n+1); dp[0] = 1,minRecord[0]=1; for (int i = 1; i <= n; i++) { if (nums[i - 1] > 0) { minRecord[i] = min(nums[i - 1], minRecord[i - 1] * nums[i - 1]); dp[i] = max(dp[i - 1] * nums[i - 1], nums[i - 1]); } else { minRecord[i] = min(nums[i - 1], dp[i - 1] * nums[i - 1]); dp[i] = max(nums[i - 1] * minRecord[i - 1], nums[i - 1]); } maxP = max(maxP, dp[i]); } return maxP; }
这里其实维护了两个dp数组,最大就是我们要要的,只需要再维护一个最小
然后众所周知,一维dp可以空间优化
int maxProduct(vector<int>& nums) { // 前面赋初值11是不合理的 // 这里的三个nums[0]初值其实都是没必要的,但循环遍历nums是必要的 int maxP = nums[0]; int maxRecord = nums[0], preMax = 1, minRecord = nums[0], preMin = 1; for (int i = 0; i < nums.size(); i++) { if (nums[i] > 0) { minRecord = min(nums[i], preMin * nums[i]); maxRecord = max(preMax * nums[i], nums[i]); } else { minRecord = min(nums[i], preMax * nums[i]); maxRecord = max(nums[i] * preMin, nums[i]); } preMax = maxRecord; preMin = minRecord; maxP = max(maxP, maxRecord); } return maxP; }
本题的关键在于需要一个额外的dp辅助数组,本题是经典最大字数和的变形
本文作者:YaosGHC
本文链接:https://www.cnblogs.com/yaocy/p/16855100.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步