编程之美2.13——子数组的最大乘积

来源:互联网 发布:vbox ubuntu 桥接模式 编辑:程序博客网 时间:2024/06/05 00:44

问题:

给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算任意(N-1)个数的组合中乘积最大的一组。


解法一:

采用空间换时间的策略,用两个数组分别记录原整数数组前缀与后缀的叠乘积(前缀s[i]=),再以间隔1个数的方式将这两个数组乘起来就得到所有n-1个数的乘积数组(具体看代码)。

#include <iostream>#include <algorithm>using namespace std;#define MAXN 1003long long A[MAXN];long long s[MAXN];long long t[MAXN];int main(){int n, i;cin >> n;for (i=1; i<=n; i++)cin >> A[i];// 从前往后用叠乘法s[0] = 1;for (i=1; i<n; i++)s[i]=A[i]*s[i-1];// 从后往前用叠乘法t[n+1] = 1;for (i=n; i>1; i--)t[i]=A[i]*t[i+1];// 计算出n-1个n-1数连乘for (i=0; i<=n-1; i++)s[i] = s[i]*t[i+2];long long maximum = s[0];// 获取其中的最大值for (i=1; i<=n-1; i++)maximum = max(maximum, s[i]);cout << maximum << endl;}
解法二:

对N个数的乘积进行分析,用启发式的方式得到在满足乘积最大情况下要删去那个数。

#include <iostream>#include <algorithm>using namespace std;#define MAXN 1003long long A[MAXN];#define INF 0x7fffffffint main(){int n, i, j;cin >> n;for (i=1; i<=n; i++)cin >> A[i];// 从前往后用叠乘法long long P = 1;for (i=1; i<=n; i++)P*=A[i];if (P==0){for (j=1; j<=n && A[j]; j++);long long Q = 1;for (i=1; i<=n; i++)if (i!=j) Q *= A[i];if (Q>=0) cout << Q << "," << j << endl;else cout << "0" << endl;}else if (P>0){for (i=1; i<=n && A[i]<0; i++);if (i<=n){long long minPos = A[i];j = i;for (i=i+1; i<=n; i++)if (A[i]>0 && A[i]<minPos){minPos = A[i];j = i;}long long Q = 1;for (i=1; i<=n; i++)if (i!=j) Q *= A[i];cout << Q << "," << j << endl;}else{long long minNeg = A[1];for (i=2; i<=n; i++)if (A[i] < minNeg){minNeg = A[i];j = i;}long long Q = 1;for (i=1; i<=n; i++)if (i!=j) Q *= A[i];cout << Q << "," << j << endl;}}else{for (i=1; i<=n && A[i]>0; i++);long long maxNeg = A[i];j = i;for (i=i+1; i<=n; i++)if (A[i]<0 && A[i]>maxNeg){maxNeg = A[i];j = i;}long long Q = 1;for (i=1; i<=n; i++)if (i!=j) Q *= A[i];cout << Q << "," << j << endl;}}