53. 最大子数组和 (最大子序和)
描述
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是数组中的一个连续部分。
链接
53. 最大子数组和 - 力扣(LeetCode) (leetcode-cn.com)
解法
对于 贪心算法而言:
- 贪心贪的是哪里呢?
- 如果 -2 1 在一起,计算起点的时候,一定是从1开始计算,因为负数只会拉低总和,这就是贪心贪的地方!
- 局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。
- 全局最优:选取最大“连续和”
- 局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。
1 class Solution { 2 // 思路1:贪心法 3 public int maxSubArray1(int[] nums) { 4 if (nums.length == 1) { 5 return nums[0]; 6 } 7 int sum = Integer.MIN_VALUE; 8 int count = 0; 9 for (int i = 0; i < nums.length; i++) { 10 count += nums[i]; 11 // 取区间累计的最大值(相当于不断确定最大子序终止位置) 12 sum = Math.max(count, sum); 13 if (count < 0) { // 负数会拉低总和,去掉,让count为0,到下一个循环重新选取 14 count = 0; 15 } 16 } 17 return sum; 18 } 19 20 // 思路2:动态规划 21 public int maxSubArray(int[] nums) { 22 if (nums.length < 1) { 23 return 0; 24 } 25 int tmpSum = 0, res = nums[0]; 26 for (int num : nums) { 27 // tmpSum + num < num 时,说明 tmpSum <= 0,需要从新的num中选取 28 tmpSum = Math.max(tmpSum + num, num); 29 // 当res < tmpSum 时,说明是之前tmpSum加的num负增益了,依然用res = res不选取 30 res = Math.max(res, tmpSum); 31 } 32 return res; 33 } 34 }
时间复杂度:O(n),额外空间复杂度O(1)
参考
carl