题目
给定一个数组,至少有一个元素。请计算子数组最大乘积是多少?
例如:
- 给定数组 [2, 3, -2, 4]
- 经过计算,得到最大乘积为6。子数组为[2,3]。
题目来自Leetcode。
分析
这个题目,有经验的同学,看过一遍,就知道肯定是动态规划了,可具体要如何规划呢?我想,有的同学还记得子数组的最大和吧?是不是觉得很激动,O(n)就可以解决了。一样的思路!但是不好意思,错了!
错在哪里呢?乘法口诀还记得么?负负得正,就可恶在这里。在加法里,负负可得不到正。
那这个题目怎么办?O(n^2)么?是否要计算保存之前的所有状态?不必如此,其实就多了数组中的元素为负情况的考虑。因为负负得正,我们除了考虑当前的最大值之外,还需要考虑当前的最小值。
原因是,如果最小值是负的,而且当前是负的,那么乘积之后是正数,很可能就大于当前最大的。
所以遍历一遍,计算以每个元素结尾的最大值最小值,最后找到全局的最大值。就是我们要的结果了。
粗糙、直白的代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| public class Solution { private int max2(int a, int b) { if (a > b) return a; return b; } private int max3(int a, int b, int c) { return max2(max2(a, b), c); } private int min2(int a, int b) { if (a < b) return a; return b; } private int min3(int a, int b, int c) { return min2(min2(a, b), c); } public int maxProduct(int[] A) { int max = A[0]; int min = A[0]; int a = max; for (int i = 1; i < A.length; ++i) { int tmpMax = max * A[i]; int tmpMin = min * A[i]; max = max3(tmpMax, tmpMin, A[i]); min = min3(tmpMax, tmpMin, A[i]); a = max2(a, max); } return a; } }
|