题目描述:
给定一个整数数组 nums
,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
1. 定义状态
经典动态规划问题,定义 dp[i] : nums中以nums[i] 结尾的具有最大和的连续子数组。取dp[i] ( 0=< i < n)的
最大值即可得到最终结果。
2.状态转移分析
假设在计算 dp[i] 时,前面的 dp[i-1],dp[i-2],...,dp[1],dp[0]都已知,nums[i]此时也是已知。根据 已知的条件,分类
讨论dp[i] 可能的情况。
2.1 如果 dp[i - 1] <= 0,以 nums[i] 结尾的具有最大和的连续子数组 ,不管nums[i] 是多少,没必要再加上一个0 或负数被拖累,
只包含自己就是具有最大和的连续子数组 。
2.2 如果 dp[i-1] > 0,num[i] 接上 dp[i-1] 对应的连续子数组 一定比num[i]孤独一人组成的连续子数组的和大。
所以dp 转移方程:
dp[i] = dp[i-1] + nums[i] ; (dp[i-1] > 0)
dp[i] = nums[i]; (dp[i-1] <= 0)
上面的状态 dp[i] 仅和它的上一个状态有关,可以将 状态数组 dp[] 压缩成状态变量。
3. 确定 dp 的 base case
动态规划的base case 是状态转移方程的起点,有时候确定 base case 是能否正确 解决 dp问题的关键。
这里的 状态转移方程从 nums[1] ,dp [1] 开始,base case 就是 dp[0],很容易得到dp[0] = nums[0]
4.确定状态转移方向
最简单的 从 nums[0] 到 nums[n-1].
代码如下 :
1 class Solution { 2 public: 3 int maxSubArray(vector<int>& nums) 4 { 5 if(nums.empty() || nums.size() == 0) return INT_MAX; 6 int dp = nums[0];//dp[i] 在nums中以nums[i]结尾的具有最大和的连续子数组 7 int res = dp; 8 for(int i = 1;i<nums.size();++i) 9 { 10 if(dp <= 0) 11 { 12 dp = nums[i]; 13 } 14 else 15 { 16 dp = dp + nums[i]; 17 } 18 res = max(res,dp); 19 } 20 return res; 21 } 22 };