最大和连续子串

来源:互联网 发布:淘宝如何批量设置运费 编辑:程序博客网 时间:2024/04/28 04:23

一、问题描述

输入一组整数,求出这个整数数组最大和的连续子串。例如,整数数组为{4, -2, 59, -45, 4},最大和的连续子串为{4, -2, 59},最大和为61。需要注意的是要求子串连续,另外,子串的长度可以是1.

这个也是曾经出过的一道面试提,最早是浙大的一道考研算法设计题。

二、问题分析

第一种方法。最简单的思路就是用两层循环来解决问题。外面一层是从1到整数数组的长度,里面的那层循环是当前的位置加1一直到整数数组的结束,里面的循环来算所有的和。换句话说就是,内层循环每次从i+1开始到字符数组结束的和,这些和是numbers[i]+numbers[i+1],numbers[i]+numbers[i+1]+numbers[i+2],...,numbers[i]+...+numbers[length(numbers)]中找到最大的那个。外层循环则是找到全局最大的那个。这个方法比较好想,只给出伪代码,这个的时间复杂度为:

下面是伪代码:

for i = 0 to length(numbers)   current = numbers[i]   for j = i + 1 to length(numbers)      current += numbers[j]      if(current_max < current)         current_max = current    end    if(max < current_max)    max = current_maxend
第二种思路可以设置一个变量current_max来保存当前作出的最大和,用一个变量max来保存全局的最大和。当加到一个负数时,当前和会减少,但是,是不是会不会改变全局最大和还需要看后面的一个元素。而如果当前的current_max变为负数了,说明如果再用这个数加后面的数只会使和变小,所以把current_max赋值为0,但是需要额外考虑的就是数组全为负数的情况。用这种方法可以把时间复杂度降到O(n)。


第三种思路可以考虑动态规划的方法,但是用动态规划解决问题的思路我还没有弄的太明白,等弄明白后在补充到这里。

三、程序实现

#include <stdio.h>#include <stdlib.h>#define MAX(a, b) ((a)>(b)?(a):(b))int main(int argc, char const *argv[]){int n,i,current_max,max;int* numbers;printf("Please input the integer n(n > 0):\n");while(EOF != (scanf("%d", &n))){numbers = (int*)malloc(n * sizeof(int));i = 0;while(i++ < n)scanf("%d", &numbers[i - 1]);printf("The computing numbers are : %d", numbers[0]);for(i = 1; i < n; i++)printf(",%d", numbers[i]);printf("\n");current_max = numbers[0];max = current_max;for(i = 1; i < n; i++){current_max += numbers[i];max = MAX(max, current_max);max = MAX(max, numbers[i]);if(0 > current_max){if((i + 1) != (n - 1))current_max = 0;elsecurrent_max = numbers[i];}}printf("the restult is : %d\n", max);free(numbers);printf("Please input the integer n(n > 0):\n");}return 0;}
看计算时的那个for循环,我的思路是先进行相加在考虑是否改变current_max和max,还有一种思路是 考虑利用上一次current_max的值来判断对current_max操作,即求和或者赋值为当前数组元素的值,之后在设置全局最大值max(见参考文献1),这里给出这种情况求和的伪代码:


max=numbers[0];       current_max=0;  for(i=0;i<n;i++)  {      if(current_max>=0)           current_max+=numbers[i];      else             current_max=numbers[i];      if(current_max>max)          max=current_max;  }

四、测试结果

我把上面两种方法(第一种是先求和在判断是否改变current_max,第二种是根据前一次的current_max来判断这次是否需要求和还是赋值current_max为当前的整数数组元素)。

第一组测试数据(只有一个数)如下图:


第二组测试数据(一负一正)如下图:


第三组测试数据(全负)如下图:


第四组测试数据(正负都有)如下图:


五、参考资料

1. 程序员编程艺术:第七章、求连续子数组的最大和:

http://blog.csdn.net/v_JULY_v/article/details/6444021


说明:

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

上述程序完整代码的下载链接:

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%20sum%20of%20continuous%20substring

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