152.乘积最大子序列
思路:
初版思路是将序列按照0拆开成若干子序列,然后在每个子序列里面判断负数的个数,若负数是偶数,直接相乘,若负数是奇数,要么从左往右相乘直到最后一个奇数,要么从右向左相乘知道第一个奇数
修改版的思路是从左往右遍历+从右往左遍历,使用dp[i]保存相应方向直接相乘到i的数值。碰到0就跳过重新开始计算。
最终版的思路是使用动态规划,记录以i点结束的最大值跟最小值,然后求max(dp_max * nums[i], dp_min * nums[i]) 与 num[i] 两者之间的最大值。常规dp。
初版:
runtime error
class Solution { public: int maxProduct(vector<int>& nums) { int len = nums.size(); if(len == 0) return 0; int odd_num = 0; int max_num = 1; for(int i = 0; i < len; i++) { if(nums[i] == 0) { vector<int> vec1(nums.begin(), nums.begin() + i); vector<int> vec2(nums.begin() + i+1, nums.end()); return max(maxProduct(vec1), maxProduct(vec2)) > 0 ? max(maxProduct(vec1), maxProduct(vec2)) : 0; } if(nums[i] < 0) odd_num++; } if(len == 1) { return nums[0]; } if(odd_num % 2 == 0) { for(auto i : nums) { max_num *= i; } return max_num; } else { bool signal = true; int max1 = 1, max2 = 1; for(auto i : nums) { if(!signal) max1 *= i; else if(i < 0) { signal = false; continue; } } signal = true; for(int i = nums.size()-1; i >= 0; i--) { if(!signal) max2 *= nums[i]; else if(nums[i] < 0) { signal = false; continue; } } return max(max1, max2); } } };
修改版:
执行用时 :8 ms, 在所有 C++ 提交中击败了77.55%的用户
内存消耗 :9.1 MB, 在所有 C++ 提交中击败了44.38%的用户
class Solution { public: int maxProduct(vector<int>& nums) { int len = nums.size(); if(len == 0) return 0; vector<int> dp_l(len); vector<int> dp_r(len); for(int i = 0; i < len; i++) { dp_l[i] = nums[i]; dp_r[i] = nums[i]; } int max_l = dp_l[0]; int max_r = dp_r[0]; for(int i = 1; i < len; i++) { if(nums[i] == 0 || dp_l[i-1] == 0) continue; dp_l[i] = dp_l[i-1] * nums[i]; max_l = max(max_l, dp_l[i]); } for(auto i : dp_l) { max_l = max(i, max_l); } for(int i = len-2; i >= 0; i--) { if(nums[i] == 0 || dp_r[i+1] == 0) continue; dp_r[i] = dp_r[i+1] * nums[i]; max_r = max(max_r, dp_r[i]); } for(auto i : dp_r) { max_r = max(i, max_r); } return max(max_l, max_r); } };
最终版:
执行用时 :4 ms, 在所有 C++ 提交中击败了95.67%的用户
内存消耗 :8.9 MB, 在所有 C++ 提交中击败了87.90%的用户
class Solution { public: int maxProduct(vector<int>& nums) { int n = nums.size(); int dp_min = nums[0], dp_max = nums[0]; int maxVal = nums[0]; for (int i = 1; i < n; ++i) { int _dp_min = dp_min * nums[i]; int _dp_max = dp_max * nums[i]; dp_min = min(nums[i], min(_dp_min, _dp_max)); dp_max = max(nums[i], max(_dp_min, _dp_max)); maxVal = max(maxVal, dp_max); } return maxVal; } };