给一个浮点数序列,取最大乘积连续子串的值,例如 -2.5,4,0,3,0.5,8,-1,则取出的最大乘积连续子串为3,0.5,8。也就是说,上述数组中,3 0.5 8这3个数的乘积3*0.5*8=12是最大的,而且是连续的。
思路1:
暴力法:将所有的可能都罗列出来,时间复杂度为O(n^2)
double maxProductSubString(double *data, int n)
{
double maxResult = data[0];
for(int i=0;imaxResult)
{
maxResult = x;
}
}
}
return maxResult;
}
思路二:
利用动态规划的方法:由于在数组中有正数和负数,所以需要记录最大的乘积和最小的乘积,maxend和minend,最小乘积乘以一个负数可能成为最大乘积,利用状态转移方程进行计算:
maxend = max(max(maxend*a[i],minend*a[i]),a[i]);
minend = min (min(maxend*a[i],minend*a[i]),a[i]);
对于元素a[i],在0-i中,要么是与maxend相乘之后变为最大乘积,要么与minend相乘变成最大乘积,或者本身就是最大乘积。
初始化都为a[]
double maxProductsubString_dynamic(double *data, int n)
{
double maxend, minend;
maxend = minend = data[0];
double result = data[0];
for(int i=1;i
时间复杂度为O(n)
1、给定一个长度为N的整数数组,只允许用乘法,不能用除法,计算任意(N-1)个数的组合中乘积最大的一组,并写出算法的时间复杂度。
分析:我们可以把所有可能的(N-1)个数的组合找出来,分别计算它们的乘积,并比较大小。由于总共有N个(N-1)个数的组合,总的时间复杂度为O(N^2),显然这不是最好的解法。
int maxN_1ProductSubString(int *data, int n)
{
int maxResult=1;
for(int k=1;k maxResult)
maxResult = produce;
}
return maxResult;
}
思路二:
一空间换时间,利用两个数组s[],t[],s[i]记录0-i元素的乘积,t[i]代表i-n-1元素的乘积,那么去除a[i]后的乘积是s[i-1]*t[i+1],由于只需要扫描两遍数组,所以时间复杂度是线性的O(n)
int maxN_1ProductSubString2(int *data, int const n)
{
int *s = new int[n];
int *t = new int[n];
s[0] = data[0];
t[n-1] = data[n-1];
for(int i=1;i=0;j--)
{
t[j] = t[j+1] * data[j];
}
int maxResult = s[0] * t[2];
for(int i=1;i maxResult)
maxResult = r;
}
return maxResult;
}
在上述的基础上,可以进行逻辑判断,减少计算量:
假设N个整数的乘积为P,针对P的正负性进行如下分析(其中,AN-1表示N-1个数的组合,PN-1表示N-1个数的组合的乘积)。
1.P为0
那么,数组中至少包含有一个0。假设除去一个0之外,其他N-1个数的乘积为Q,根据Q的正负性进行讨论:
Q为0
说明数组中至少有两个0,那么N-1个数的乘积只能为0,返回0;
Q为正数
返回Q,因为如果以0替换此时AN-1中的任一个数,所得到的PN-1为0,必然小于Q;
Q为负数
如果以0替换此时AN-1中的任一个数,所得到的PN-1为0,大于Q,乘积最大值为0。
2. P为负数
根据“负负得正”的乘法性质,自然想到从N个整数中去掉一个负数,使得PN-1为一个正数。而要使这个正数最大,这个被去掉的负数的绝对值必须是数组中最小的。我们只需要扫描一遍数组,把绝对值最小的负数给去掉就可以了。
3. P为正数
类似地,如果数组中存在正数值,那么应该去掉最小的正数值,否则去掉绝对值最大的负数值。在时间复杂度方面,由于只需要遍历数组一次,在遍历数组的同时就可得到数组中正数(+)、负数(-)和0的个数,以及数组中绝对值最小的正数和负数,时间复杂度为O(N)。
#define MAX_Postive 100
#define MIN_Negative -100
int maxN_1ProductSubString3(int *data, int const n)
{
int *s = new int[n];
int *t = new int[n];
s[0] = data[0];
t[n-1] = data[n-1];
for(int i=1;i=0;j--)
{
t[j] = t[j+1] * data[j];
}
int num_zero=0,num_postive=0,num_negative=0;
int position_min_postive,position_max_negative,position_zero;
int min_postive = MAX_Postive;
int max_negative = MIN_Negative;
for(int k=0;k0)
{
++num_postive;
if(data[k]< min_postive)
{
position_min_postive = k;
min_postive = data[k];
}
}else
{
++num_negative;
if(data[k]>max_negative)
{
position_max_negative = k;
max_negative = data[k];
}
}
}
int maxResult;
if(num_zero != 0)
{
if(num_zero == 1)
{
if(num_negative % 2 ==0)
{
if(position_zero == 0)
maxResult = t[1];
else if(position_zero == n-1)
maxResult = s[n-2];
else
maxResult = s[position_zero-1]*t[position_zero+1];
}else
maxResult = 0;
}else
{
maxResult = 0;
}
}else
{
if(num_negative %2 == 0)
{
if(position_min_postive == 0)
maxResult = t[1];
else if(position_min_postive == n-1)
maxResult = s[n-2];
else
maxResult = s[position_min_postive-1]*t[position_min_postive+1];
}else
{
if(position_max_negative == 0)
maxResult = t[1];
else if(position_max_negative == n-1)
maxResult = s[n-2];
else
maxResult = s[position_max_negative-1]*t[position_max_negative+1];
}
}
return maxResult;
}