13.最大子数组的和
给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
是数组中的一个连续部分。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1] 输出:1
示例 3:
输入:nums = [5,4,-1,7,8] 输出:23
方法1: dp
从0~i 最大和连续子数组
dp[i]={dp[i−1]+nums[i] , if dp[i−1]>0
nums[i] , if dp[i−1]≤0 }
最大值在dp[i]中,不是dp[-1]
class Solution { public int maxSubArray(int[] nums) { int[] dp = new int[nums.length]; dp[0] = nums[0]; for(int i=1; i<nums.length; i++){ if(dp[i-1] > 0) dp[i] = dp[i-1] + nums[i]; else dp[i] = nums[i]; } int max = dp[0]; for(int i=1;i<nums.length; i++){ if(max < dp[i]) max=dp[i]; } return max; } }
精简版
public class Solution { public int maxSubArray(int[] nums) { int pre = 0; int res = nums[0]; for (int num : nums) { pre = Math.max(pre + num, num); res = Math.max(res, pre); } return res; } } 作者:liweiwei1419 来源:力扣(LeetCode)
方法2: 前缀和——好巧妙啊
首先明确前缀和的定义:
对于数组 nums = [a1, a2, a3, ..., an],它的前缀和数组 preSum 定义为:preSum[i] = a1 + a2 + ... + ai
那么任意连续子数组 nums[j...i] 的和 = preSum[i] - preSum[j-1]。
代码的核心逻辑是:
- 遍历数组,实时计算当前前缀和
preSum; - 对每个
preSum,计算它与之前最小前缀和的差值,更新最大值max; - 同时更新 “之前最小前缀和”
min,为后续计算做准备。
class Solution { public int maxSubArray(int[] nums) { // 边界处理:数组为空或null时返回一个极小值(实际题目保证数组非空,可简化) if(nums==null||nums.length==0) return -99999; int max=-99999; // 记录最大子数组和,初始为极小值 int min=0; // 记录遍历过程中最小的前缀和,初始为preSum[0]=0 int preSum=0; // 实时计算当前前缀和 for (int num : nums) { preSum += num; // 计算当前前缀和(对应preSum[i]) // 关键1:当前前缀和 - 之前最小前缀和 = 以当前位置结尾的最大子数组和 max = Math.max(max, preSum - min); // 关键2:更新最小前缀和,供下一次计算使用 min = Math.min(min, preSum); } return max; } }
os: 数组好容易和dp搞到一起🤔
【暴力会超时】
class Solution { public int maxSubArray(int[] nums) { int sum = Integer.MIN_VALUE, tmp = 0; for(int i=0; i<nums.length; i++){ tmp=0; for(int j=i; j<nums.length; j++){ tmp+=nums[j]; if(tmp>sum) sum=tmp; } } return sum; } }

浙公网安备 33010602011771号