最大乘积连续子串

陌路散爱 提交于 2020-11-20 08:37:56

一、问题描述

输入一组浮点数,求出这个浮点数组最大乘积的连续子串。举个例子,浮点数组为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的过程中记录一下当前的起止位置。这个可由读者自行思考。


说明:

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

上述程序完整代码的下载链接:
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


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!