微软面试题: LeetCode 53. 最大子序和 出现次数:3

题目描述:

  给定一个整数数组 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 };

 

posted @ 2020-11-17 00:08  谁在写西加加  阅读(53)  评论(0编辑  收藏  举报