子数组的最大乘积

《编程之美》 2.13

问题:给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算(N-1)个数的组合乘积中最大的一组,并写出算法的时间复杂度。

解法一:把所有N-1个数的组合找出来,分别计算乘积,比较大小。O(N^2)。

int MaxSubProducti(int a[],int n)
{
	assert(n > 1);
	int i,j,k,prod,ret;
	for (i = 0; i < n; i++){
		prod = 1;
		for(j = 0; j < i; j++){
			prod *= a[j];
		}
		for(j = i + 1; j < n; j++){
			prod *= a[j];
		}
		if (i == 0) ret = prod;
		if (prod > ret) ret = prod;
	}
	return ret;
}

int MaxSubProductii(int a[],int n)
{
	assert(n > 1);
	int i,j,prod,ret;
	for(i = 0; i < n; i++){
		prod = 1;
		for(j = 0; j < n; j++){
			prod *= (i == j) ? 1 : a[j];
			if (prod == 0)// terminate early
				break;
		}
		if (i == 0) ret = prod;
		if (prod > ret)	ret = prod;
	}
	return ret;	
}

解法二:利用两个数组s和s分别表示从数组a的两端开始计算的乘积,s[i] = a[0]*a[1]*...*a[i-1],t[j] = a[j]*...*a[n-1]。那么p[i] = s[i-1] * t[i+1]。时间复杂度为O(N)。

int MaxSubProductiii(int a[],int n)
{
	assert(n > 1);
	int *s = (int *)malloc(n*sizeof(int));
	int *t = (int *)malloc(n*sizeof(int));
	int i,j,lowprod,highprod,maxprod,prod;
	lowprod = 1;
	highprod = 1;
	assert(s != NULL && t != NULL);
	
	for(i = 0; i < n; i++){
		j = n - i - 1;
		lowprod *= a[i];
		highprod *= a[j];
		s[i] = lowprod;
		t[j] = highprod;
	}
	maxprod = (s[n-2] > t[1]) ? s[n-2] : t[1];
	for(i = 1; i < n - 1; i ++){
		prod = s[i-1] * t[i+1];
		if (prod > maxprod) maxprod = prod;
	}
	free(s);
	free(t); 
	return maxprod;
}

解法三:统计数组中正数、负数和零的个数,记录最小的正数、负数以及最大的负数。

1,如果零的个数n_zero大于1,那么最大乘积为0;

2,如果零的个数n_zero为1:

(1),如果负数的个数n_neg为奇数,那么最大乘积为0;

(2),如果负数的个数n_neg为偶数,那么最大乘积计算式扣除a[zeroi];

3,如果零的个数n_zero为0:

(1),如果负数的个数n_neg为奇数,那么最大乘积计算式扣除a[maxnegi];

(2),如果负数的个数n_neg为偶数:

1> 如果正数的个数n_pos为零,那么最大乘积计算式扣除a[minnegi];

2> 如果正数的个数n_pos大于零,那么最大乘积计算式扣除a[minposi];

int MaxSubProductiv(int *a, int n)
{
	int n_zero = 0; // count of zero 
	int n_neg = 0;  // count of negative integer
	int n_pos = 0;
	int maxneg = 0; // maximum negative integer 
	int minpos = 0; // minimum positive integer 
	int maxnegi = 0; // index of maxneg
	int minposi = 0; // index of minimum positive integer
	int zeroi = 0;   // index of zero
	int minneg = 0;
	int minnegi = 0;
	int out = -1;    // index of the val to be omitted 
	                 // when calculating result product
	int max = 1;
	
	/* collect some statistic info in one loop */
	for(int i = 0; i < n; i++)
	{
		if(a[i] < 0)  //a[i] is negative
		{
			n_neg++;
			if(maxneg == 0)
			{
				maxneg = a[i];
				maxnegi = i;
			}
			else if(maxneg < a[i])
			{
				maxneg = a[i];
				maxnegi = i;
			}
			
			if (minneg == 0) {
				minneg = a[i];
				minnegi = i;
			}
			else if (minneg > a[i]) {
				minneg = a[i];
				minnegi = i;
			}
		}
		else if(a[i] == 0) // a[i] is zero
		{
			zeroi = i;
			if(++n_zero > 1) return 0;
		}
		else // a[i] is positive
		{
			n_pos++;
			if(minpos == 0)
			{
				minpos = a[i];
				minposi = i;
			}
			else if(minpos > a[i])
			{
				minpos = a[i];
				minposi = i;
			}
		}
	}
 
 
	if((n_zero == 1) && (n_neg & 0x1))
	{
		// one zero and odd negatives
		return 0;
	}
	else if((n_zero == 1) && !(n_neg & 0x1))
	{
		// one zero and even negatives
		printf("one zero and even negatives\n");
		out = zeroi;
	}
	else if((n_zero == 0) && (n_neg & 0x1))
	{
		// no zero and odd negatives
		printf("no zero and odd negatives\n");
		out = maxnegi;
	}
	else if((n_zero == 0) && !(n_neg & 0x1))
	{
		// no zero and even negatives
		printf("no zero and even negatives\n");
		if (n_pos == 0){
			out = minnegi;
		}
		else {
			out = minposi;
		}
	}
	
	for(int i = 0; i < n; i++)
	{
		max *= (i == out) ? 1 : a[i];
	}
	return max;
}

int MaxSubProductv(int *a, int n)
{
	int n_zero = 0; // count of zero 
	int n_neg = 0;  // count of negative integer
	int n_pos = 0;  // count of positive integer
	int maxneg = 0; // maximum negative integer 
	int minpos = 0; // minimum positive integer 
	int maxnegi = 0; // index of maxneg
	int minposi = 0; // index of minimum positive integer
	int zeroi = 0;   // index of zero
	
	int minneg = 0;
	int minnegi = 0;
	
	int out = -1;         // index of the val to be omitted 
	                 // when calculating  product
	int max = 1;
	
	for(int i = 0; i < n; i++)
	{
		if(a[i] < 0)  //a[i] is negative
		{
			n_neg++;
			if(maxneg == 0)
			{
				maxneg = a[i];
				maxnegi = i;
			}
			else if(maxneg < a[i])
			{
				maxneg = a[i];
				maxnegi = i;
			}
			
			if (minneg == 0){
				minneg = a[i];
				minnegi = i; 
			}
			else {
				if (minneg > a[i]){
					minneg = a[i];
					minnegi = i;
				}
			} 
		}
		else if(a[i] == 0) // a[i] is zero
		{
			zeroi = i;
			if(++n_zero > 1) return 0;
		}
		else // a[i] is positive
		{
			n_pos++;
			if(minpos == 0)
			{
				minpos = a[i];
				minposi = i;
			}
			else if(minpos > a[i])
			{
				minpos = a[i];
				minposi = i;
			}
		}
	}
 
 	if (n_zero){
 		printf("zeros.\n");
 		if (n_neg & 1)
 			return 0;
 		else
 			out = zeroi;
 	}
 	else {
 		printf("no zero.\n");
 		if (n_neg & 1)
 			out = maxnegi;
 		else if (n_pos == 0){
 			out = minnegi;
 		}
 		else {
 			out = minposi;
 		}
 	}
		
	for(int i = 0; i < n; i++)
	{
		max *= (i == out) ? 1 : a[i];
	}
	return max;
}

测试程序:

#include <stdio.h>
#include <assert.h>
#include <time.h>
#include <stdlib.h>


int MaxSubProducti(int a[],int n)
{
	assert(n > 1);
	int i,j,k,prod,ret;
	for (i = 0; i < n; i++){
		prod = 1;
		for(j = 0; j < i; j++){
			prod *= a[j];
		}
		for(j = i + 1; j < n; j++){
			prod *= a[j];
		}
		if (i == 0) ret = prod;
		if (prod > ret) ret = prod;
	}
	return ret;
}

int MaxSubProductii(int a[],int n)
{
	assert(n > 1);
	int i,j,prod,ret;
	for(i = 0; i < n; i++){
		prod = 1;
		for(j = 0; j < n; j++){
			prod *= (i == j) ? 1 : a[j];
			if (prod == 0)// terminate early
				break;
		}
		if (i == 0) ret = prod;
		if (prod > ret)	ret = prod;
	}
	return ret;	
}

int MaxSubProductiii(int a[],int n)
{
	assert(n > 1);
	int *s = (int *)malloc(n*sizeof(int));
	int *t = (int *)malloc(n*sizeof(int));
	int i,j,lowprod,highprod,maxprod,prod;
	lowprod = 1;
	highprod = 1;
	assert(s != NULL && t != NULL);
	
	for(i = 0; i < n; i++){
		j = n - i - 1;
		lowprod *= a[i];
		highprod *= a[j];
		s[i] = lowprod;
		t[j] = highprod;
	}
	maxprod = (s[n-2] > t[1]) ? s[n-2] : t[1];
	for(i = 1; i < n - 1; i ++){
		prod = s[i-1] * t[i+1];
		if (prod > maxprod) maxprod = prod;
	}
	free(s);
	free(t); 
	return maxprod;
}

int MaxSubProductiv(int *a, int n)
{
	int n_zero = 0; // count of zero 
	int n_neg = 0;  // count of negative integer
	int n_pos = 0;
	int maxneg = 0; // maximum negative integer 
	int minpos = 0; // minimum positive integer 
	int maxnegi = 0; // index of maxneg
	int minposi = 0; // index of minimum positive integer
	int zeroi = 0;   // index of zero
	int minneg = 0;
	int minnegi = 0;
	int out = -1;    // index of the val to be omitted 
	                 // when calculating result product
	int max = 1;
	
	/* collect some statistic info in one loop */
	for(int i = 0; i < n; i++)
	{
		if(a[i] < 0)  //a[i] is negative
		{
			n_neg++;
			if(maxneg == 0)
			{
				maxneg = a[i];
				maxnegi = i;
			}
			else if(maxneg < a[i])
			{
				maxneg = a[i];
				maxnegi = i;
			}
			
			if (minneg == 0) {
				minneg = a[i];
				minnegi = i;
			}
			else if (minneg > a[i]) {
				minneg = a[i];
				minnegi = i;
			}
		}
		else if(a[i] == 0) // a[i] is zero
		{
			zeroi = i;
			if(++n_zero > 1) return 0;
		}
		else // a[i] is positive
		{
			n_pos++;
			if(minpos == 0)
			{
				minpos = a[i];
				minposi = i;
			}
			else if(minpos > a[i])
			{
				minpos = a[i];
				minposi = i;
			}
		}
	}
 
 
	if((n_zero == 1) && (n_neg & 0x1))
	{
		// one zero and odd negatives
		return 0;
	}
	else if((n_zero == 1) && !(n_neg & 0x1))
	{
		// one zero and even negatives
		printf("one zero and even negatives\n");
		out = zeroi;
	}
	else if((n_zero == 0) && (n_neg & 0x1))
	{
		// no zero and odd negatives
		printf("no zero and odd negatives\n");
		out = maxnegi;
	}
	else if((n_zero == 0) && !(n_neg & 0x1))
	{
		// no zero and even negatives
		printf("no zero and even negatives\n");
		if (n_pos == 0){
			out = minnegi;
		}
		else {
			out = minposi;
		}
	}
	
	for(int i = 0; i < n; i++)
	{
		max *= (i == out) ? 1 : a[i];
	}
	return max;
}

int MaxSubProductv(int *a, int n)
{
	int n_zero = 0; // count of zero 
	int n_neg = 0;  // count of negative integer
	int n_pos = 0;  // count of positive integer
	int maxneg = 0; // maximum negative integer 
	int minpos = 0; // minimum positive integer 
	int maxnegi = 0; // index of maxneg
	int minposi = 0; // index of minimum positive integer
	int zeroi = 0;   // index of zero
	
	int minneg = 0;
	int minnegi = 0;
	
	int out = -1;         // index of the val to be omitted 
	                 // when calculating  product
	int max = 1;
	
	for(int i = 0; i < n; i++)
	{
		if(a[i] < 0)  //a[i] is negative
		{
			n_neg++;
			if(maxneg == 0)
			{
				maxneg = a[i];
				maxnegi = i;
			}
			else if(maxneg < a[i])
			{
				maxneg = a[i];
				maxnegi = i;
			}
			
			if (minneg == 0){
				minneg = a[i];
				minnegi = i; 
			}
			else {
				if (minneg > a[i]){
					minneg = a[i];
					minnegi = i;
				}
			} 
		}
		else if(a[i] == 0) // a[i] is zero
		{
			zeroi = i;
			if(++n_zero > 1) return 0;
		}
		else // a[i] is positive
		{
			n_pos++;
			if(minpos == 0)
			{
				minpos = a[i];
				minposi = i;
			}
			else if(minpos > a[i])
			{
				minpos = a[i];
				minposi = i;
			}
		}
	}
 
 	if (n_zero){
 		printf("zeros.\n");
 		if (n_neg & 1)
 			return 0;
 		else
 			out = zeroi;
 	}
 	else {
 		printf("no zero.\n");
 		if (n_neg & 1)
 			out = maxnegi;
 		else if (n_pos == 0){
 			out = minnegi;
 		}
 		else {
 			out = minposi;
 		}
 	}
		
	for(int i = 0; i < n; i++)
	{
		max *= (i == out) ? 1 : a[i];
	}
	return max;
}


void show(int a[],int n)
{
	for(int i = 0; i < n; i++){
		printf("%-3d",a[i]);
	}
	printf("\n");
}
int main()
{
	int a[6];
	int N = 6;
	srand(time(NULL));
	for(int i = 0; i < N; i++){
		a[i] = rand() % 10 ; 
		if (a[i] & 0x1)
			a[i] = -a[i];
	}
	show(a,N);
	printf("Max Sub Product of N-1 elements: %d .\n",MaxSubProducti(a,N));
	printf("Max Sub Product of N-1 elements: %d .\n",MaxSubProductii(a,N));
	printf("Max Sub Product of N-1 elements: %d .\n",MaxSubProductiii(a,N));
	printf("Max Sub Product of N-1 elements: %d .\n",MaxSubProductiv(a,N));
	printf("Max Sub Product of N-1 elements: %d .\n",MaxSubProductv(a,N));
} 

测试输出:

2  -5 -5 -5 -7 2  
Max Sub Product of N-1 elements: 1750 .
Max Sub Product of N-1 elements: 1750 .
Max Sub Product of N-1 elements: 1750 .
no zero and even negatives
Max Sub Product of N-1 elements: 1750 .
no zero.
Max Sub Product of N-1 elements: 1750 .


REF:

1,编程之美 2.13



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值