1. 程式人生 > 其它 >【LeetCode】53.最大子序和

【LeetCode】53.最大子序和

給定一個整數陣列 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 casedp[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;
    }
};