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...
方法一:字首和
思路和演算法
- 都是負數的情況下 每次都是sum為當前值,依次與maxsum比較取其中最大的。
- 正常情況下(有正有負)累計字首和,只要sum大於0 (還有存在價值),就加上來,判斷與前面的maxsum誰大,取較大值;
- 當前和變小到0時(說明前面的負數抵消了,後面來的數不管是正是負,前面累計的和0都沒價值了),則重新從當前數開始,同時保證子陣列的連續性。
- 注意不是遇到負數就重新賦值。另外需要不停的判斷當前和是不是最大的。
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;
}