zoukankan      html  css  js  c++  java
  • (3): 求子数组的最大和

    目:输入一个整形数组,数组里有正数也有负数。数组中连续的一个或多个整数组成一个子数组,每个子数组都有一个和。求所有子数组的和的最大值。要求时间复杂度为O(n)

    例如输入的数组为1, -2, 3, 10, -4, 7, 2, -5,和最大的子数组为3, 10, -4, 7, 2,因此输出为该子数组的和18

    分析:本题最初为2005年浙江大学计算机系的考研题的最后一道程序设计题,在2006年里包括google在内的很多知名公司都把本题当作面试题。由于本题在网络中广为流传,本题也顺利成为2006年程序员面试题中经典中的经典。

    如果不考虑时间复杂度,我们可以枚举出所有子数组并求出他们的和。不过非常遗憾的是,由于长度为n的数组有O(n2)个子数组;而且求一个长度为n的数组的和的时间复杂度为O(n)。因此这种思路的时间是O(n3)

    很容易理解,当我们加上一个正数时,和会增加;当我们加上一个负数时,和会减少。如果当前得到的和是个负数,那么这个和在接下来的累加中应该抛弃并重新清零,不然的话这个负数将会减少接下来的和。基于这样的思路,我们可以写出如下代码。

    参考代码:

    /////////////////////////////////////////////////////////////////////////////
    // Find the greatest sum of all sub-arrays
    // Return value: if the input is valid, return true, otherwise return false
    /////////////////////////////////////////////////////////////////////////////
    bool FindGreatestSumOfSubArray
    (
          int *pData,           // an array
          unsigned int nLength, // the length of array
          int &nGreatestSum     // the greatest sum of all sub-arrays
    )
    {
          // if the input is invalid, return false
          if((pData == NULL) || (nLength == 0))
                return false;

          int nCurSum = nGreatestSum = 0;
          for(unsigned int i = 0; i < nLength; ++i)
          {
                nCurSum += pData[i];

                // if the current sum is negative, discard it
                if(nCurSum < 0)
                      nCurSum = 0;

                // if a greater sum is found, update the greatest sum
                if(nCurSum > nGreatestSum)
                      nGreatestSum = nCurSum;

          }


          // if all data are negative, find the greatest element in the array
          if(nGreatestSum == 0)
          {
                nGreatestSum = pData[0];
                for(unsigned int i = 1; i < nLength; ++i)
                {
                      if(pData[i] > nGreatestSum)
                            nGreatestSum = pData[i];
                }
          }

          return true;
    }

    讨论:上述代码中有两点值得和大家讨论一下:

    ·         函数的返回值不是子数组和的最大值,而是一个判断输入是否有效的标志。如果函数返回值的是子数组和的最大值,那么当输入一个空指针是应该返回什么呢?返回0?那这个函数的用户怎么区分输入无效和子数组和的最大值刚好是0这两中情况呢?基于这个考虑,本人认为把子数组和的最大值以引用的方式放到参数列表中,同时让函数返回一个函数是否正常执行的标志。

    ·         输入有一类特殊情况需要特殊处理。当输入数组中所有整数都是负数时,子数组和的最大值就是数组中的最大元素。

    《编程珠机》第八章,8.4扫描算法。

    采用类似分治算法的道理:前i个元素中,最大综合子数组要么在i-1个元素中(maxsofar),要么截止到位置i(maxendinghere)。

    做个快乐的自己。
  • 相关阅读:
    Uva 10779 collector's problem
    poj 2728 最优比率树(最小生成树问题)
    LA 3126 二分图匹配 最小路径覆盖
    poj 1149 最大流构图
    Step By Step(Java XML篇)
    Step By Step(Java 输入输出篇)
    Step By Step(Java 集合篇)
    Step By Step(Java 线程篇)
    Step By Step(Java 反射篇)
    Step By Step(Java 国际化篇)
  • 原文地址:https://www.cnblogs.com/Jessy/p/1868306.html
Copyright © 2011-2022 走看看