连续子数组中最大和
1:题目描述
输入一个整型数组,数组里有正数也有负数。数组中的一个或连续多个整数组成一个子数组。求所有子数组的和的最大值。
要求时间复杂度为O(n)。
示例1:
输入: nums = [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
提示:
1 <= arr.length <= 10^5
-100 <= arr[i] <= 100
注意:本题与主站 53 题相同:https://leetcode-cn.com/problems/maximum-subarray/
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2:题目分析
题目要求时间复杂度为O(n),则很显然暴力搜索法不能满足要求。所以如何能做到O(n),则只有一遍遍历数组就能求得结果的情况下,才是满足题目要求。
2.1:贪心算法
class Solution { //遍历数组,如果当前之和小于0,则意味着会对后面的数据和产生负影响, //如果为正则正影响, // 所以当此时和为负时,将之前sum不要了,此时sum等于当前数组值即可,用来统计后面的字串之和, //用一个变量保存sum和的出现的最大值即可。 public int maxSubArray(int[] nums) { //初始化为nums[0] int resultSum = nums[0]; int sum = 0; //遍历数组,如果此时sum小于0,则将当前num赋值给sum。 //意味着,抛弃前面的数组之和了。 for(int i=0;i<nums.length;i++){ if(sum<=0){ sum = nums[i]; } else{ //如果sum不为0,意味着还会有正影响,则继续加上。 sum = sum + nums[i]; } //记录出现过的最大值即可 if(sum >resultSum){ resultSum = sum; } } return resultSum; }
2.2:动态规划
动态规划的分析如下,以后分析动态规划问题就借鉴这位同学的分析方式。
(作者:jyd
链接:https://leetcode-cn.com/problems/lian-xu-zi-shu-zu-de-zui-da-he-lcof/solution/mian-shi-ti-42-lian-xu-zi-shu-zu-de-zui-da-he-do-2/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。)
状态定义:
设动态规划列表 dpdp ,dp[i]dp[i] 代表以元素 nums[i]nums[i] 为结尾的连续子数组最大和。
为何定义最大和 dp[i]dp[i] 中必须包含元素 nums[i]nums[i] :保证 dp[i]dp[i] 递推到 dp[i+1]dp[i+1] 的正确性;如果不包含 nums[i]nums[i] ,递推时则不满足题目的 连续子数组 要求。
转移方程:
若 dp[i-1] \leq 0dp[i−1]≤0 ,说明 dp[i - 1]dp[i−1] 对 dp[i]dp[i] 产生负贡献,即 dp[i-1] + nums[i]dp[i−1]+nums[i] 还不如 nums[i]nums[i] 本身大。
当 dp[i - 1] > 0dp[i−1]>0 时:执行 dp[i] = dp[i-1] + nums[i]dp[i]=dp[i−1]+nums[i] ;
当 dp[i - 1] \leq 0dp[i−1]≤0 时:执行 dp[i] = nums[i]dp[i]=nums[i] ;
初始状态: dp[0] = nums[0]dp[0]=nums[0],即以 nums[0]nums[0] 结尾的连续子数组最大和为 nums[0]nums[0] 。
返回值:
返回 dpdp 列表中的最大值,代表全局最大值。