一、问题描述
输入一组浮点数,求出这个浮点数组最大乘积的连续子串。举个例子,浮点数组为str[]={-3,-5,0,-1,-2,-2},这时得出来的结果是前两个浮点数的乘积,即15。需要注意的是,这个子串是要求连续的,另外,子串的长度可以为1.
二、问题分析
这里给出两种思路,后续可能还会加入新的思路。
第一种是直接求解。即用双层循环。外面一层是从1到浮点数组的长度,里面的那层循环是当前的位置加1一直到浮点数组的结束,里面的循环来算所有的乘积。换句话说就是,内层循环每次从i+1开始到浮点数组结束的乘积,这些乘积是str[i]*str[i+1],str[i]*str[i+1]*str[i+2],...,str[i]*...*str[length(str)]中找到最大的那个。外层循环则是找到全局最大的那个。这个方法比较好想,只给出伪代码。下面是伪代码:
for i = 0 to length(str)
current = str[i]
for j = i + 1 to length(str)
current *= str[j]
if(current_max < current)
current_max = current
end
if(max < current_max)
max = current_max
end
第二种思路就是如果当前已经找到一个序列的最大的值为current_max,那么加入数组中的下一个值会是什么结果呢?如果要乘以大于1的正数的话,显然current_max的值还会增大,但要乘以一个小于-1的负数的话,current_max则会变成一个当前最小的数。所以,我们可以在找最大乘积序列的时候同时找一下最小乘积序列。这样一来,如果是乘以一个大于1的正数的话 current_max还是当前最大的,current_min还是当前最小的。但是乘以一个小于-1的负数的话,则current_max变成了当前最小的而current_min变成了当前最大的,这时可以交换current_max和current_min的值。而当乘以一个绝对值小于1的数的话current_max会变小,current_min会变大,所以另外需要一个全局变量来单独记录最大的乘积(max)和最小值乘积(min)。这里还需要注意一点,如果当前最大值小于1时,需要记录str[i],并与全局最大值max比较一下。具体可以看下面的程序实现。
三、程序实现
#include <stdio.h>
#define MAX_BUF 1024
int main(int argc, char *argv[])
{
double str[MAX_BUF];
int n,
i;
double max_multi_substring(double *, const int);
while(EOF != (scanf("%d", &n)))
{
for(i = 0; i < n; i++)
scanf("%lf", &str[i]);
printf("%lf\n", max_multi_substring(str, n));
printf("end\n");
}
return 0;
}
double max_multi_substring(double *str, const int length)
{
double max = str[0];
double min = str[0];
double current_max = str[0];
double current_min = str[0];
int i = 1;
for (; i < length; i++)
{
current_max *= str[i];
current_min *= str[i];
if(current_max > max)
max = current_max;
if(current_min > max)
max = current_min;
if(current_max < min)
min = current_max;
if(current_min < min)
min = current_min;
if(current_max < current_min)
{
double temp = current_max;
current_max = current_min;
current_min = temp;
}
if(current_max < 1)
{
current_max = str[i];
if(current_max > max)
max = current_max;
}
}
return max;
}
四、测试结果
数据1(含有一个正数):{1}; 结果:1;
数据2(含有一个负数):{-0.2}; 结果:-0.2;
数据3(含一组正小数):{0.5, 0.8, 0.6, 0.7};结果:0.8;
数据4(一组正负小数):{0.5, 0.9, -0.6, 0.7, -0.7};结果:0.9;
数据5(正负相间正数):{-2, 3, 4, -2, -4};结果:96;
数据6(正负整数随机):{-2, -2, 6, 8, -4, 8};结果:192;
数据7(正负整数小数):{2, -0.5, 0.7, 4, -6};结果:16.8。
五、参考资料
1. 3月面试集训第2周回顾 最大乘积连续子串:
http://hero.pongo.cn/Question/Details?ID=19&ExamID=19
2. 第二十八~二十九章 最大连续乘积子串、字符串编辑距离:
http://blog.csdn.net/v_july_v/article/details/8701148
六、后续任务
接下来需要输出这个乘积最大的子序列怎么实现,实现可以在更新全局最大值max的过程中记录一下当前的起止位置。这个可由读者自行思考。
说明:
如有错误还请各位指正,欢迎大家一起讨论给出指导。
最后更新时间:2013-05-03
来源:oschina
链接:https://my.oschina.net/u/264813/blog/127189