leetcode#152 Maximum Product Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest product.
For example, given the array [2,3,-2,4],
the contiguous subarray [2,3] has the largest product = 6.
解释
给定一个数组,要求找出数组的一个连续子集(子集中至少包括一个元素),该子集中元素之积最大。
我的解法
leetcode53是关于数组的最大加和子集的问题,在加和的问题中,如果遇到负数使得整体的和值小于0,那么前面的和值都可以不要,而从当前位置的值开始计算加和——毕竟加一个负数会使得最后的和值更小。
但是在本题中,由于负负得正,所以尽管之前的乘积值为负值,也可能会在最后遇到一个新的负值,使得整体的乘积转为正数。
大神解法
解法一:非DP
既然存在负负得正的情况,那么就索性保留当前乘积值的最小值(如果有负数的话,就选取最小的负数,负负得正就是最大的),同时保留当前乘积值的最大值——保留一大一小的乘积值,一直遍历到最后,整个过程都在判断两个值的大小关系。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public int maxProduct(int[] A) { if (A.length == 0) { return 0; } int maxherepre = A[0]; int minherepre = A[0]; int maxsofar = A[0]; int maxhere, minhere; for (int i = 1; i < A.length; i++) { maxhere = Math.max(Math.max(maxherepre * A[i], minherepre * A[i]), A[i]); minhere = Math.min(Math.min(maxherepre * A[i], minherepre * A[i]), A[i]); maxsofar = Math.max(maxhere, maxsofar); maxherepre = maxhere; minherepre = minhere; } return maxsofar; }
|
解法二:DP
其实DP的思路与非DP的思路是一样的——都是保留一大一小两个值,只不过DP用了一个数据结构来保存乘积值,好处在于如果想知道在哪个位置的乘积值达到最大,可以通过保存乘积值的数组获悉。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public class Solution { public int maxProduct(int[] A) { if (A == null || A.length == 0) { return 0; } int[] f = new int[A.length]; int[] g = new int[A.length]; f[0] = A[0]; g[0] = A[0]; int res = A[0]; for (int i = 1; i < A.length; i++) { f[i] = Math.max(Math.max(f[i - 1] * A[i], g[i - 1] * A[i]), A[i]); g[i] = Math.min(Math.min(f[i - 1] * A[i], g[i - 1] * A[i]), A[i]); res = Math.max(res, f[i]); } return res; } }
|