程序員面試題精選100題(03)-子數組的最大和[算法]

題目:輸入一個整形數組,數組裏有正數也有負數。數組中連續的一個或多個整數組成一個子數組,每個子數組都有一個和。求所有子數組的和的最大值。要求時間複雜度爲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這兩中情況呢?基於這個考慮,本人認爲把子數組和的最大值以引用的方式放到參數列表中,同時讓函數返回一個函數是否正常執行的標誌。

·         輸入有一類特殊情況需要特殊處理。當輸入數組中所有整數都是負數時,子數組和的最大值就是數組中的最大元素。

轉自:http://zhedahht.blog.163.com/blog/static/254111742007219147591/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章