最大乘积连续子串

来源:互联网 发布:windows任务栏全透明 编辑:程序博客网 时间:2024/04/29 14:26

一、问题描述

输入一组浮点数,求出这个浮点数组最大乘积的连续子串。举个例子,浮点数组为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_maxend


第二种思路就是如果当前已经找到一个序列的最大的值为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 1024int 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的过程中记录一下当前的起止位置。这个可由读者自行思考。


说明:

如有错误还请各位指正,欢迎大家一起讨论给出指导。

上述程序完整代码的下载链接:
https://github.com/zeliliu/BlogPrograms/tree/master/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%26%E7%AE%97%E6%B3%95/max%20multi%20substring

最后更新时间:2013-05-03


原创粉丝点击