题目链接
题目描述
{6, -3, -2, 7, -15, 1, 2, 2},连续子数组的最大和为 8(从第 0 个开始,到第 3 个为止)。
解题思路
动态规划解析:
状态定义: 设动态规划列表 dp ,dp[i] 代表以元素 nums[i] 为结尾的连续子数组最大和。
- 为何定义最大和 dp[i] 中必须包含元素 nums[i] :保证 dp[i] 递推到 dp[i+1] 的正确性;如果不包含 nums[i] ,递推时则不满足题目的 连续子数组 要求。
转移方程: 若 dp[i−1]≤0 ,说明 dp[i−1] 对 dp[i] 产生负贡献,即 dp[i−1]+nums[i] 还不如 nums[i] 本身大。
- 当 dp[i−1]>0 时:执行dp[i]=dp[i−1]+nums[i] ;
- 当 dp[i−1]≤0 时:执行 dp[i]=nums[i] ;
- 初始状态: dp[0]=nums[0],即以 nums[0] 结尾的连续子数组最大和为 nums[0] 。
返回值: 返回 dp 列表中的最大值,代表全局最大值。

空间复杂度降低:
- 由于 dp[i] 只与 dp[i-1] 和 nums[i] 有关系,因此可以将原数组 nums 用作 dp 列表,即直接在 nums 上修改即可。
- 由于省去 dp 列表使用的额外空间,因此空间复杂度从 O(N) 降至 O(1) 。
class Solution {public:int FindGreatestSumOfSubArray(vector<int> array) {int n = array.size();if(n==0)return 0;int max,dp;max = dp = array[0];for(int i=1;i<n;i++){if(dp<0)dp = array[i];elsedp=dp+array[i];max = dp>max?dp:max;}return max;}};
- 时间复杂度 O(N) : 其中 N 为字符串长度,动态规划需遍历计算 dp 列表。
- 空间复杂度 O(1)
返回最大和的子数组
class Solution {public int[] maxSubArray(int[] nums) {// right为当前最大和的子数组右坐标// s为子数组长度// count为子数组中间计数int right = 0, s = 0, count = 0;// 利用dp不改变原始数组int[] dp = new int[nums.length];dp[0] = nums[0];for(int i = 1; i < nums.length; ++i){if(nums[i] < nums[i] + dp[i-1]){dp[i] = nums[i] + dp[i-1];// 连续 计数加一++count;}else{dp[i] = nums[i];// 断开连续,重新计数count = 0;}if(dp[i] > dp[right]){// 出现更大的值,记录子数组右坐标和长度right = i;s = count;}}// 复制右坐标int[] res = new int[s + 1];for(int i = right - s, j = 0; i <= right; ++i,++j){res[j] = nums[i];}return res;}}
