每日一練(22):連續子陣列的最大和

加班猿發表於2022-02-24

title: 每日一練(22):連續子陣列的最大和

categories:[劍指offer]

tags:[每日一練]

date: 2022/02/21


每日一練(22):連續子陣列的最大和

輸入一個整型陣列,陣列中的一個或連續多個整陣列成一個子陣列。求所有子陣列的和的最大值。

要求時間複雜度為O(n)。

示例1:

輸入: nums = [-2,1,-3,4,-1,2,1,-5,4]

輸出: 6

解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。

提示:

1 <= arr.length <= 10^5

-100 <= arr[i] <= 100

來源:力扣(LeetCode)

連結:https://leetcode-cn.com/probl...

方法一:字首和

思路和演算法

  1. 都是負數的情況下 每次都是sum為當前值,依次與maxsum比較取其中最大的。
  2. 正常情況下(有正有負)累計字首和,只要sum大於0 (還有存在價值),就加上來,判斷與前面的maxsum誰大,取較大值;
  3. 當前和變小到0時(說明前面的負數抵消了,後面來的數不管是正是負,前面累計的和0都沒價值了),則重新從當前數開始,同時保證子陣列的連續性。
  4. 注意不是遇到負數就重新賦值。另外需要不停的判斷當前和是不是最大的。
int maxSubArray(vector<int>& nums) {
    int maxSum = nums[0];    //預設第一個數為最大值
    int sum = 0;
    for (int i = 0; i < nums.size(); i++) {                
        sum = sum <= 0 ? nums[i] : sum + nums[i];// 當前和不大於0時,說明前面抵消了,從新開始累計和;同樣的如果都是負數時,則依次比較哪個最大,賦值給maxSum
        maxSum = sum > maxSum ? sum : maxSum;            // 不停比較更新maxSum
    }
    return maxSum;
}

方法二:動態規劃(DP方程)

思路和演算法

最原始的動態規劃

  • 狀態:dp[i]:以第i個數結尾的和的最大值
  • 轉移:若dp[i - 1] < 0,則以第i個數結尾的和的最大值為第i個數本身
  • 若dp[i - 1] > 0,則以第i個數結尾的和的最大值為的dp[i - 1]與dp[i - 1] + nums[i]中的較大者
  • 避免遍歷dp陣列,每次比較dp更新結束後比較res與dp[i]的大小作為返回值
int maxSubArray(vector<int>& nums) {
    int len = nums.size();
    vector<int> dp(len);
    dp[0] = nums[0];
    int res = nums[0];
    for (int i = 1; i < len; i++) {
        //判斷
        if(dp[i - 1] > 0) {
            dp[i] = max(dp[i - 1] + nums[i], nums[i]);
        } else {
            dp[i] = nums[i];
        }
        //三目運算子
        //dp[i] = (dp[i - 1] > 0) ? dp[i] = max(dp[i - 1] + nums[i], nums[i]) : nums[i];
        res = max(res, dp[i]);
    }
    return res;
}

相關文章