劍指offer——連續子陣列的最大和(42題)
阿新 • • 發佈:2018-12-14
題目:輸入一個整型陣列,數組裡有正數也有負數。陣列中的一個或連續多個整陣列成一個子陣列。求所有子陣列的和的最大值。要求時間複雜度為O(n)。
此題同時也是leetcode的原題。此處用兩種方法解答。方法一,叫不出名字,但只需一次遍歷,看程式碼很好理解。方法二,利用動態規劃,dp[i]中儲存以第i位置結尾的子序列的最大和。然後最後再求dp中的最大值。方法二的求解複雜度可能會稍高些,但不失為一種方法。
注意:以下程式碼均沒有考慮特殊值輸入的條件。如果需要,其思想是,應該設定一個全域性變數,一旦檢測出輸入陣列錯誤時,需要修改全域性變數後才返回函式(這一步驟省略了,不好意思)。
方法一程式碼:
int maxSumOfSubarray1(vector<int>& nums) { int curSum = 0, ret = (int)0x80000000; for (int i = 0; i < nums.size(); ++i) { curSum += nums[i]; ret = (curSum > ret ? curSum : ret);//這一步隱含:子序列的最後一位數字絕不可能是負值 if (curSum < 0) curSum = 0; } return ret; }
方法二:
//利用動態規劃思想 /* f(i)表示以第i個數字結尾的子陣列的最大和 當i=0或者f(i-1)<=0, f(i)=nums[i] 當f(i-1)<=0時,f(i)即為第i+1個數字本身 當f(i-1)>0,f(i)=f(i-1)+nums[i] 當f(i-1)>0時,f(i)即為以第i-1個數字結尾的子陣列中所有數字的和與第i個數字累加所得結果 */
程式碼如下:
int maxSumOfSubarray2(vector<int>& nums) { vector<int> dp(nums.size(), 0); dp[0] = nums[0]; for (int i = 1; i < nums.size(); ++i) { if (dp[i - 1] <= 0) dp[i] = nums[i]; else dp[i] = dp[i - 1] + nums[i]; } vector<int>::iterator it = max_element(dp.begin(), dp.end()); return *it; }
驗證程式碼:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main() {
vector<int> nums = { 1,-2,3,10,-4,7,2,-5 };
int ret1,ret2;
ret1 = maxSumOfSubarray1(nums);
ret2 = maxSumOfSubarray2(nums);
return 0;
}