编程之美读书笔记2.13—子数组的最大乘积

1.时间复杂度O(N^2)

2.时间复杂度O(N),组A[N],设去除第i个元素的乘积为A[0]*A[1]*…A[i-1] * A[i+1]*A[i+2]*…A[N-1],则可以写出如下算法满足复杂度为Ο(N)。  

    设f[i]=A[0]*A[1]*…A[i], r[i]=A[i]*A[i+1]*…A[N]则p[i] = f[i-1]*r[i+1]。

3.时间复杂度O(N),进一步减少计算量。子数组最大乘积问题可以分为以下几种情况。  

1.数组中有多于一个零则最大乘积为0;

2.数组中只有一个零,而有奇数个负数,则最大乘积必定为0;

3.数组中只有一个零,而有偶数个负数,则最大乘积为除去0的元素的乘积;  

4.数组中没有零,而有奇数个负数,则最大乘积为除去绝对值最小的负数的乘积;  

5.数组中没有零,而有偶数个负数,则最大乘积为除去最小的正数的乘积。

遍历一遍数组得到数组中正数、负数,零的个数,以及绝对值最小的正数和负数

#include<iostream>
#include<cstdlib>
#include<ctime>
using namespace std;

long long LevelOne(int data[],int maxsize)
{
	long long max=0;
	for (int i=0;i<maxsize;i++)
	{ 
		int ret=1;
		for (int j=0; j<maxsize; j++)
		{
			if(i!=j)
			{	ret*=data[j];
	            if(data[j]==0)
			          break;
			}
		 }
		  max = (max<=ret ? ret : max);
	}
	return max;
}

long long LevelTwo( int *d, unsigned int n)
{
	int *f=new int [n];
	int *r=new int [n];
	long long *p = new long long [n];
	long long max=0;
	long long fv=1,rv=1;
	for(int i=0; i<n; i++)
	{
		int j = n-i-1;
		fv *= d[i];
		rv *= d[j];
		f[i] = fv;
		r[j] = rv;
	}
	
	max = r[1];
	for(int i=1; i<n-1; i++)
	{
	     p[i] = f[i-1] * r[i+1];
		 max = max<p[i] ? p[i] : max;
	}
	delete [] f;
	delete [] r;
	delete [] p;
	return max;
}

long long LevelThree(int *d, int n)
{
	int n_zero = 0;
	int n_neg = 0;
	int maxneg = 0;
	int minpos = 0;
	int maxnegi = 0;
	int minposi = 0;
	int zeroi = 0;
	int out;
	long long max = 1;

	for(int i=0; i<n; i++)
	{

		if(d[i] < 0)
		{
			n_neg++;     //负数个数
			if(maxneg == 0)     //最大负数
			{
				maxneg = d[i];
				maxnegi = i;
			}
			else if(maxneg<d[i])
			{
				maxneg = d[i];
				maxnegi = i;
			}
		}
		else if(d[i] == 0)
		{
			zeroi = i;
			if(++n_zero>1) return 0;  //至少两个0,返回结果0
		}
		else
		{
			if(minpos == 0)
			{
				minpos = d[i];
				minposi = i;
			}
			else if(minpos > d[i])        //最小正数
			{
				minpos = d[i];
				minposi = i;
			}
		}
	}

	if(n_zero==1 && n_neg%2==1)    
	{
		return 0;
	}
	else if(n_zero==1 && n_neg%2==0)
	{
		out = zeroi;
	}
	else if(n_zero==0 && n_neg%2==1)
	{
		out = maxnegi;
	}
	else if(n_zero==0 && n_neg%2==0)
	{
		out = minposi;
	}

	for(int i=0; i<n; i++)
	{
		max *= (i==out)?1:d[i];
	}
	return max;
}
int main()
{
	const int maxsize = 10;
	int data[maxsize];
	long long max1,max2,max3;

	srand(time(NULL));

	for(int i=0; i<maxsize; i++)
	    data[i] = ((rand()%10<2) ? -1:1) * (rand()%10);
		
	for(int i=0; i<maxsize; i++)
		cout<<data[i]<<" ";
	cout<<endl;
		
	 max1 = LevelOne(data, maxsize);
	 cout<<"max: "<<max1<<endl;
	 
	 max2= LevelTwo(data, maxsize);
	 cout<<"max: "<<max2<<endl;	

	 max3= LevelThree(data, maxsize);
	 cout<<"max: "<<max3<<endl;

	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值