算法题11:最大子数组和
题目描述:
给你一个整数数组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
思路:
前缀和 + 贪心
由于子数组的元素和等于两个前缀和的差,所以求出nums的前缀和问题就变成买卖股票的最佳时机了,要求子数组不能为空,相当于一定要交易一次。
买卖股票这个题还没做过后面再说。
我们可以一边遍历数组计算前缀和,一边维护前缀和的最小值(相当于股票最低价格),用当前的前缀和(卖出价格)减去前缀和的最小值(买入价格),
就得到了以当前元素结尾的子数组和的最大值(利润),用它来更新答案的最大值(最大利润)。
请注意,由于题目要求子数组不能为空,应先计算当前前缀和 - 最小前缀和,再更新最小前缀和。相当于不能在同一天买入股票又卖出。
如果先更新最小前缀和,在计算前缀和 - 最小前缀和,那么有可能就是当前的前缀和减去自己,答案就变成了0,即结果为空数组。
python
class Solution: def maxSubArray(self, nums: List[int]) -> int: ans = -inf min_pre_sum, pre_sum = 0, 0 for i in nums: pre_sum += i # 当前的前缀和 ans = max(ans, pre_sum - min_pre_sum) # 减去前缀和的最小值 min_pre_sum = min(min_pre_sum, pre_sum) # 减去前缀和的最小值 return ans
Java
class Solution { public int maxSubArray(int[] nums) { int ans = Integer.MIN_VALUE; int minPreSum = 0; int preSum = 0; for(int i: nums) { preSum += i; // 当前的前缀和 ans = Math.max(ans, preSum - minPreSum); // 减去前缀和的最小值 minPreSum = Math.min(minPreSum, preSum); // 维护前缀和最小值 } return ans; }
结果:


浙公网安备 33010602011771号