152. 乘积最大子数组
https://leetcode-cn.com/problems/maximum-product-subarray/
看到题目一开始想着用滑动窗口去做,但是遇到了负数和0,直接pass想法。
然后采用暴力解,发现爆内存了。
再想着暴力的优化,结果过了,击败了5%的人。
class Solution { public int maxProduct(int[] nums) { if(nums.length == 0){ return 0; } if(nums.length == 1){ return nums[0]; } int[] dp = new int[nums.length]; int max = Integer.MIN_VALUE; for(int i = 0; i < dp.length; i++){ dp[i] = nums[i]; max = Math.max(max, dp[i]); for(int j = i+1; j < dp.length;j++){ dp[j] = dp[j-1] * nums[j]; max = Math.max(dp[j],max); } } return max; } }
但是这很明显是个垃圾算法,我试着继续优化。
这个题很大程度是取决于这个负数和0的位置。我试着把O(n^2)的时间复杂度继续优化,优化到O(n+m),但是好像失败了,只能看评论区。
class Solution { public int maxProduct(int[] nums) { if(nums.length == 0){ return 0; } int max = nums[0]; int[][] dp = new int[nums.length][2]; dp[0][0] = nums[0]; dp[0][1] = nums[0]; for(int i= 1; i< nums.length; i++){ int minValue = nums[i] * dp[i-1][0]; int maxValue = nums[i] * dp[i-1][1]; dp[i][0] = Math.min(minValue,Math.min(maxValue, nums[i])); dp[i][1] = Math.max(maxValue, Math.max(minValue,nums[i])); max = Math.max(dp[i][1],max); } return max; } }
这个代码有点像那个股票的买卖,dp数组的第二维记录下了当前坐标下的最大值和最小值。
偶数个负数会把最小值变成最大值,而奇数个负数会把最大值变成最小值,这个大概就是这种思想吧。然后使用一个max来记录下出现过的最大值,最后返回即可。