求数组中n-1个元素的乘积的最大值(某公司2007年校园招聘笔试试题)

        原题只要求写思路,不要求写程序,但要分析算法的时空复杂度,下面我们来看看如何解决这个问题:

        方法1:直接翻译题意,将n-1个元素的积求出来,然后求最大值,当然,这是最笨的方法,Google当然不欣赏这种做法:

 

#include <iostream>
#define M 10
#define N 5
using namespace std;

int a[M][N] =
{
	{-6, -5, -4, -3, -2},  // (-6)*(-5)*(-4)*(-3) = 360
	{-6, -5, -4, -3,  2},  // 360
	{-6, -5, -4,  3,  2},  // 180
	{-6, -5,  4,  3,  2},  // 360
	{-6,  5,  4,  3,  2},  // 120
	{ 6,  5,  4,  3,  2},  // 360
	{-6,  5,  4,  3,  0},  // 0
	{-6, -5,  4,  0,  0},  // 0
	{ 6,  5,  4,  3,  0},  // 360
	{ 6,  5,  4,  0,  0}   // 0
};

int getBiggest(int x[], int n)
{
	int *p = new int[n];
	int i, j, multi, biggest;
	for(i = 0; i < n; i++)
	{
		multi = 1;
		for(j = 0; j < n; j++)
		{
			if(j != i) 
			{
				// 求除去i位置外的有所元素的积
				multi *= x[j];
			}
		}
		p[i] = multi;
	}

	biggest = p[0];
	for(i = 1; i < n; i++)
	{
		if(p[i] > biggest)
		{
			biggest = p[i];
		}
	}

	delete []p;

	return biggest;
}

int main()
{
	int i;
	for(i = 0; i < M; i++)
	{
		cout << getBiggest(a[i], N) << endl;
	}

	return 0;
}

 

 


       方法2:考虑用除法,比方法1要好,如下:

 

#include <iostream>
#define M 10
#define N 5
using namespace std;

int a[M][N] =
{
	{-6, -5, -4, -3, -2},  // (-6)*(-5)*(-4)*(-3) = 360
	{-6, -5, -4, -3,  2},  // 360
	{-6, -5, -4,  3,  2},  // 180
	{-6, -5,  4,  3,  2},  // 360
	{-6,  5,  4,  3,  2},  // 120
	{ 6,  5,  4,  3,  2},  // 360
	{-6,  5,  4,  3,  0},  // 0
	{-6, -5,  4,  0,  0},  // 0
	{ 6,  5,  4,  3,  0},  // 360
	{ 6,  5,  4,  0,  0}   // 0
};

// 计算0个个数
int numOfZero(int x[], int n)
{
	int i, numZero = 0;
	for(i = 0; i < n; i++)
	{
		if(0 == x[i])
		{
			numZero++;
		}
	}

	if(0 == numZero)
		return 0;

	if(1 == numZero)
		return 1;

	return 2; // 0的个数大于或等于2
}

// n个元素的乘积
int getTotalMulti(int x[], int n)
{
	int i, totalMulti = 1;
	for(i = 0; i < n; i++)
	{
		totalMulti *= x[i];
	}
	
	return totalMulti;
}

// n-1个元素乘积的最大值
int getBiggest(int x[], int n)
{
	if(2 == numOfZero(x, n))    // 两个0的情况
		return 0;

	int i,biggest = 1;
	if(1 == numOfZero(x, n))    // 一个0的情况
	{
		for(i = 0; i < n; i++)
		{
			if(0 != x[i])
			{
				biggest *= x[i];  // biggest是除0外所有元素的积
			}
		}

		return biggest < 0 ? 0 : biggest;
	
	}

	// 以下是所有元素非零的情况
	int totalMulti = getTotalMulti(x, n);
	biggest = totalMulti/x[0];
	int tmp;
	for(i = 1; i < n; i++)
	{
		tmp = totalMulti/x[i];
		if(tmp > biggest)
		{
			biggest = tmp;
		}
	}

	return biggest;
}

int main()
{
	int i;
	for(i = 0; i < M; i++)
	{
		cout << getBiggest(a[i], N) << endl;
	}

	return 0;
}


        

 

       方法3: 可以不用除法,下面,我就不写程序了,只给出思路,有兴趣的读者可以自己去实现,思路如下:

 

    设这n个数的乘积为M,

    1 若M<0,则剔除其中最大的负整数即可;
    2 若 M=0,
        2.1 若这 N 个数中有且仅有一个为0:

              2.1.1如果其他数之积为正,则剔除0;

              2.1.2如果其他数之积为负数,否则剔除最大的负整数;

        2.2 若这 N 个数中至少有两个为0,则随便剔除一个数均可;


    3 如果 M>0,如果有正数,则剔除其中最小的正整数即可;如果没有正数,剔除最小的负整数。
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值