53. 最大子数组和:
题目链接 :53. 最大子数组和
题目:
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
思路1:动态规划
-
首先分析题目要求可得,目标是得到数组元素的连续最大和,这个和可以是一个元素,但必须保证是连续n个元素之和。
-
解决有后效性问题:有后效性指的是前面计算得到的子问题得到的值会被后序子问题的计算修改,恰如本题中,如果我们设置子问题状态位“经过某元素的最大子数组和”,那么意味着所有经过dp[i]元素的子数组序列都要经历重复计算修改。
-
最优子结构:由上文我们可以得到最优子结构为:dp[i]为以nums[i]元素结尾的最大子数组和。
-
状态转移方程:因为最优子结构中规定了,我们每次得到的子数组和中一定包含nums[i],那么根据和的累计效应,我们可以得到两种处理方式,目的都旨在获得区间内最大值:
(1)若nums[i-1]>0,说明可以正常使用nums[i-1]来为最大子数组和做贡献:dp[i]=dp[i−1]+nums[i]
(2)若nums[i-1]<=0,说明对以i结尾的最大子数组和为负贡献,不纳入最大的计算当中,由因为nums[i]是必须加入数组和中的,所以:dp[i]=nums[i]
例如按照给定输入获得的dp数组记录如下,只有遇到严格递增的nums[i]元素才能增长当前最大递增子序列的长度。
时间复杂度:使用了一次O(n)级别的循环遍历,可得O(n) 额外空间复杂度:使用了n长度的dp数组记录更新长度,得到O(n)(此处可优化为使用常数个变量的O(1)级别但不利于思路学习。)
AC代码:
class Solution {
public int maxSubArray(int[] nums) {
/**
状态:
*/
int len=nums.length;
int[] dp=new int[len];
dp[0]=nums[0];
for(int i=1;i<nums.length;i++)
{
if(dp[i-1]>0)
{
dp[i]=nums[i]+dp[i-1];
}
else{
dp[i]=nums[i];
}
}
int ans=dp[0];
for(int i=0;i<len;i++)
{
ans=Math.max(ans,dp[i]);
}
return ans;
}
}