【LeetCode】53.最大子序和
阿新 • • 發佈:2021-08-15
給定一個整數陣列 nums,找到一個具有最大和的連續子陣列(子陣列最少包含一個元素),返回其最大和。
示例 1:
輸入:nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出:6
解釋:連續子陣列[4,-1,2,1] 的和最大,為6 。
演算法1(動態規劃)
時間複雜度:\(O(N)\)
dp陣列定義:常規思路下,我們可能會想到用dp[i]
代表nums[0...i]
最大的子陣列和,但是如果這樣定義,我們無法通過dp[i]
推出dp[i+1]
,因為擁有最大和的連續子陣列不一定和nums[i+1]
是連續的。所以為了關聯當前的nums[i]
,我們定義dp[i]
代表以nums[i]
結尾的連續子陣列的最大和。
狀態轉移:根據dp陣列的定義我們可以推出,以
nums[i+1]
結尾的最大子陣列和,要麼和以nums[i]
結尾的最大和子陣列連在一起,要麼自己自成一派。所以狀態轉移方程即為dp[i+1] = max(nums[i], dp[i-1]+nums[i])
。base case:
dp[0]
的最大子陣列即為nums[0]
自己(因為nums[0]
之前沒有元素了)
class Solution { public: int maxSubArray(vector<int>& nums) { if (nums.size() == 0) return 0; vector<int> dp(nums.size()); dp[0] = nums[0]; for (int i = 1; i < nums.size(); i ++ ) { dp[i] = max(nums[i], dp[i - 1] + nums[i]); } int res = -1e6; for (auto num : dp) { res = max(res, num); } return res; } };
演算法2(動態規劃優化)
因為dp[i]
的值僅與dp[i-1]
的值有關,所以我們可以狀態壓縮進行優化,不需要dp陣列存在所有的值,只需要每次更新dp[i-1]
和dp[i]
的值即可。
class Solution { public: int maxSubArray(vector<int>& nums) { if (nums.size() == 0) return 0; int dp_0 = nums[0]; //base case int dp_1 = 0; int res = dp_0; //result for (int i = 1; i < nums.size(); i ++ ) { dp_1 = max(nums[i], nums[i] + dp_0); dp_0 = dp_1; res = max(res, dp_0); } return res; } };