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

问题:

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


解法一:

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

#include <iostream>
#include <algorithm>
using namespace std;

#define MAXN 1003
long 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 1003
long long A[MAXN];

#define INF 0x7fffffff

int 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;
	}
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值