Leetcode——53. 最大子数组和
遇到连续子数组和问题,可以试着从前缀和入手。求出前缀和后,发现其实就是每个位置的前缀和减去之前前缀和的最小值,最后得到差的最大值即可。
class Solution {
public:int maxSubArray(vector<int>& nums) {int sum = 0;int minSum = 0;int ans = INT_MIN;for(int x : nums){sum += x;ans = max(ans, sum - minSum);minSum = min(minSum, sum);}return ans;}
};
不过,在此基础上也可以观察到,该问题是可以分解为小范围的子问题。从第一个数字入手,没添加一个新数字,最大连续子数组的和要么连上该数字,要么就以该数字为新的起点。所以动态规划代码如下:
class Solution {
public:int maxSubArray(vector<int>& nums) {int n = nums.size();vector<int> dp(n, -1);dp[0] = nums[0];int ans = dp[0];for(int i = 1; i < n; i++){dp[i] = max(dp[i - 1] + nums[i], nums[i]);// 或// dp[i] = max(dp[i - 1], 0) + nums[0];ans = max(ans, dp[i]);}// 注, 答案不是dp[n - 1]// 而是整个dp数组的最大值return ans;}
};
空间优化:
class Solution {
public:int maxSubArray(vector<int>& nums) {int n = nums.size();//vector<int> dp(n, -1);//dp[0] = nums[0];int f = nums[0];int ans = f;for(int i = 1; i < n; i++){//dp[i] = max(dp[i - 1] + nums[i], nums[i]);f = max(f, 0) + nums[i];// 或// dp[i] = max(dp[i - 1], 0) + nums[i];ans = max(ans, f);}// 注, 答案不是dp[n - 1]// 而是整个dp数组的最大值return ans;}
};