寻找和最大的最长子串

问题:

给你一个整型数组,其中的元素有正有负也有0,要求你找到一个连续的子串,子串的所有元素之和是所有的连续子串中最大的,而且是非负的。(应该讲清楚了吧?^_^)

解决方法:

最简单而又最高效的方法应该就是《编程珠玑》上介绍的扫描法了吧。其基本思想是假设以【0~(i-1)】为下标区间的子串中的最大子向量的元素之和,以及以下标 i-1 为截止元素的最大子向量之和已经求出,则当扫描到下标为 i 的元素时,这两个最大和应该做如何改变?

具体操作可以这样:

通过一个变量保存遍历到当前位置为止所找到的最大连续子串的元素之和,假设为max

通过另一个变量temp用来保存以当前位置上的元素作为最后一个元素的连续子串的元素之和,要求该连续子串的元素之后是非负的。

一开始,max和temp都是0,然后从数组第一个元素开始扫描,当扫描到一个元素a[index]时,看看将这个元素加入到当前连续子串之后,更 新的temp是否会小于0,如果小于0,则temp重置,当前连续子串变成空串,然后继续往下扫描;如果temp不小于0,则当前元素加入当前连续子串, 然后看temp是否比当前记录的max要大,如果是,则用temp来更新max,以记录当前真正的最大子串之和。如此一直到扫描一遍结束,则最大子串的和 就知道了。当然,如果还需要知道和最大的最长子串的各个元素,则还要多加几个变量,多做一些判断。

int findMaxSequence(const int * seq, int n, int * start, int * end)

/* seq为传入的整型数组,n为数组长度, start, end分别用来返回所找到的最长子串的起始下标和截止下标 */

{

          int maxsofar = 0, maxendinghere = 0;
          int starthere = 0;
          *start = *end = 0;

          for ( int i = 0; i < n; i++ )
          {
               if ( maxendinghere + seq[i] >= 0 )
                    maxendinghere = maxendinghere + seq[i];
               else
               {
                   maxendinghere = 0;
                   starthere = i+1;
               }
               if ( maxendinghere > maxsofar ||
                ((maxendinghere == maxsofar) && (*end - *start) < (i - starthere))
               {
                 maxsofar = maxendinghere;
                  *start = starthere;
                 *end = i;
               }
          }

           return maxsofar;

}

延伸下,对本问题可以产生至少2个变体问题(也是《编程珠玑》上来的),一个是寻找最长的连续子串,使得和最小且非正,另一个是使得和最接近于某个整数m。

前一个问题比较简单,其实就是和最大这个问题的一个逆问题而已。第二个问题ms有点难,反正我现在还不知道怎么一遍搞定^_^。

posted on 2011-05-06 19:36  _Clarence  阅读(380)  评论(0编辑  收藏  举报

导航