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

本文介绍两种算法解决数组中求取N-1个数的最大乘积问题。第一种使用迭代法,通过前后扫描数组计算乘积;第二种根据不同情况讨论并优化计算过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题:

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

 

方法一:迭代法

s[i]表示数组前i个元素的乘积。s[i]=s[i-1]*array[i-1]

t[i]表示数组后(N-i)个元素的乘积。t[i]=t[i+1]*array[i]

p[i]表示数组除第i个元素之外,其他N-1个元素的乘积

p[i]=s[i-1] * t[i+1]

由于只需要从头至尾,和从尾至头,扫描数组两次,进而线性时间可以得到p[]

时间复杂度O(N),若要空间复杂度小点的话,可以采用下面的链接中第8题的方法:http://blog.csdn.net/huahuahailang/article/details/8824585

 

#include<iostream>
using namespace std;
#define N 10
int main()
{
	int array[N];
	int s[N];
	int t[N];
	int p[N];
	int i;
	int max;
	cout<<"请输入"<<N<<"个数字"<<endl;
	for (i=0;i<N;i++)
	{
		cin>>array[i];
	}
	s[0]=1;//i的前部分
	for (i=1;i<N;i++)
	{
		s[i] =s[i-1]*array[i-1];
	}
	t[N-1]=1;//i的后部分
	for (i=N-2;i>=0;i--)
	{
		t[i]=t[i+1]*array[i+1];
	}
	//整合
	for (i=0;i<N;i++)
	{
		p[i]=s[i]*t[i];
	}
	//比较最大值
	max=p[0];
	for (i=1;i<N;i++)
	{
		if (p[i]>max)
		{
			max=p[i];
		}
	}
	cout<<max<<endl;
	return 0;
}


2、方法二

p=array[0]*array[1]*.......array[N-1]

p有3中情况:0,正数,负数

1、p为0的时候,则数组中至少有一个0,除去一个0后,其他N-1个乘积为Q,

      Q=0,则max=0,

      Q>0,则max=Q,

      Q<0,则max=0

2、p>0,则如果数组中有正数,找到最小的正数min,去掉最小的正数,得到乘积Q就是max,

               如果数组中只有负数,找到最小的负数min,去掉最小的负数,得到乘积Q就是max,

3、p<0,  则数组中存在负数,找到最大的负数max,去掉最大的负数,得到乘积Q就是max,

代码如下:

#include<iostream>
using namespace std;
#define N 10
int main()
{
	int array[N];
	int P,Q;
	int i;
	int position;
	int max,min;
	int flag=0;
	cout<<"请输入"<<N<<"个数字"<<endl;
	P=1;
	for (i=0;i<N;i++)
	{
		cin>>array[i];
		P *=array[i];
	}
	if (P==0)
	{
		for (i=0;i<N;i++)
		{
			if (array[i]==0)
			{
				position=i;
				break;
			}
		}
		Q=1 ;
		for (i=0;i<N;i++)
		{
			if (i!=position)
			{
				Q *=array[i];
			}
		}
		if (Q==0)
		{
			max=0;
		} 
		else
		{
			if (Q>0)
			{
				max=Q;
			} 
			else
			{
				max=0;
			}
		}
		cout<<max<<endl;
	} 
	else
	{
		if (P>0)
		{
			for (i=0;i<N;i++)
			{
				if (array[i]>0)
				{
					if (flag==0)
					{
						min=array[i];
						position=i;
						flag++;
					} 
					else
					{
						if (min>array[i])
						{
							min=array[i];
							position=i;
						}
					}
				} 
			}
			if (flag==0)//只有负数
			{
				for (i=0;i<N;i++)
				{
					if (flag==0)
					{
						min=array[i];
						position=i;
						flag++;
					} 
					else
					{
						if (min>array[i])
						{
							min=array[i];
							position=i;
						}
					}
				}
			}
			Q=1 ;
			for (i=0;i<N;i++)
			{
				if (i!=position)
				{
					Q *=array[i];
				}
			}
			max=Q;
			cout<<max<<endl;
		} 
		else
		{
			for (i=0;i<N;i++)
			{
				if (array[i]<0)
				{
					if (flag==0)
					{
						min=array[i];
						position=i;
						flag++;
					} 
					else
					{
						if (min<array[i])
						{
							min=array[i];
							position=i;
						}
					}
				}
			}
			Q=1;
			for (i=0;i<N;i++)
			{
				if (i!=position)
				{
					Q *=array[i];
				}
			}
			max=Q;
			cout<<max<<endl;
		}
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值