因为数组中存在正负零的情况,所以相比求连续子数组最大和的问题,求最大积稍微复杂一些,不过代码还是很简洁。
假设数组为a[N],max[N] 表示以下标为 i 结尾的子数组乘积最大值,min[N] 表示以下标为 i 结尾的子数组乘积最小值。
为了处理数组元素为负的问题,必须将最小乘积也保存起来。很容易想到,若当前元素a[i]为负数,那么a[i]*max[i-1]得到的值并不一定比a[i]*min[i-1]大,因为min[i-1]可能为负,如果min[i-1]的绝对值大于max[i-1],那么a[i]*min[i-1]负负相乘的值是更大的,因此有转移方程:
max[i] = MaxinThree(a[i], a[i]*max[i-1], a[i]*min[i-1]); //求三者最大
min[ i] = MininThree(a[i], a[i]*max[i-1], a[i]*min[i-1]); //求三者最小
形成代码:
- int MaxSubProduct(int a[], int n) //求子序列最大乘积,正负零都存在
- {
- int *max = new int[n];
- int *min = new int[n];
- max[0] = a[0];
- min[0] = a[0];
- int product = max[0];
- for (int i=1; i<n; i++)
- {
- max[i] = MaxinThree(a[i], a[i]*max[i-1], a[i]*min[i-1]); //求三者最大
- min[i] = MininThree(a[i], a[i]*max[i-1], a[i]*min[i-1]); //求三者最小
- if (max[i] > product)
- product = max[i];
- }
- delete [] max;
- delete [] min;
- return product;
- }
求三者最大最小的函数如下:
- int MaxinThree(int a, int b, int c)
- {
- return (((a>b)?a:b)>c) ? (a>b?a:b) : c;
- }
- int MininThree(int a, int b, int c)
- {
- return (((a<b)?a:b)<c) ? (a<b?a:b) : c;
- }