子数组的最大乘积

来源:互联网 发布:网络前端设计师 编辑:程序博客网 时间:2024/05/16 08:36

《编程之美》 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 earlybreak;}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 integerint n_pos = 0;int maxneg = 0; // maximum negative integer int minpos = 0; // minimum positive integer int maxnegi = 0; // index of maxnegint minposi = 0; // index of minimum positive integerint zeroi = 0;   // index of zeroint minneg = 0;int minnegi = 0;int out = -1;    // index of the val to be omitted                  // when calculating result productint 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 negativesreturn 0;}else if((n_zero == 1) && !(n_neg & 0x1)){// one zero and even negativesprintf("one zero and even negatives\n");out = zeroi;}else if((n_zero == 0) && (n_neg & 0x1)){// no zero and odd negativesprintf("no zero and odd negatives\n");out = maxnegi;}else if((n_zero == 0) && !(n_neg & 0x1)){// no zero and even negativesprintf("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 integerint n_pos = 0;  // count of positive integerint maxneg = 0; // maximum negative integer int minpos = 0; // minimum positive integer int maxnegi = 0; // index of maxnegint minposi = 0; // index of minimum positive integerint zeroi = 0;   // index of zeroint minneg = 0;int minnegi = 0;int out = -1;         // index of the val to be omitted                  // when calculating  productint 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 earlybreak;}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 integerint n_pos = 0;int maxneg = 0; // maximum negative integer int minpos = 0; // minimum positive integer int maxnegi = 0; // index of maxnegint minposi = 0; // index of minimum positive integerint zeroi = 0;   // index of zeroint minneg = 0;int minnegi = 0;int out = -1;    // index of the val to be omitted                  // when calculating result productint 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 negativesreturn 0;}else if((n_zero == 1) && !(n_neg & 0x1)){// one zero and even negativesprintf("one zero and even negatives\n");out = zeroi;}else if((n_zero == 0) && (n_neg & 0x1)){// no zero and odd negativesprintf("no zero and odd negatives\n");out = maxnegi;}else if((n_zero == 0) && !(n_neg & 0x1)){// no zero and even negativesprintf("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 integerint n_pos = 0;  // count of positive integerint maxneg = 0; // maximum negative integer int minpos = 0; // minimum positive integer int maxnegi = 0; // index of maxnegint minposi = 0; // index of minimum positive integerint zeroi = 0;   // index of zeroint minneg = 0;int minnegi = 0;int out = -1;         // index of the val to be omitted                  // when calculating  productint 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 negativesMax Sub Product of N-1 elements: 1750 .no zero.Max Sub Product of N-1 elements: 1750 .


REF:

1,编程之美 2.13



0 0
原创粉丝点击