先说题目
给你一个整数数组 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
题目链接:https://leetcode-cn.com/problems/maximum-subarray
再看一下官方题解
lass Solution {
public static int maxSubArray(int[] nums) {
int res = nums[0];
int sum = 0;
for (int num : nums) {
if (sum > 0)
sum += num;
else
sum = num;
res = Math.max(res, sum);
}
return res;
}
}
第一次看我是懵了但是 但是啊 我发现了一个非常好理解的帖子
可以直接拉到最下看原文
假设有这样一个数组: [a, b , c, d , e]
之前我们遍历他的子串或者子数组都是以开头遍历的
如 [a],[a, b],[ a, b, c] … 再从以 b 为开头的子序列开始遍历 [b] [b, c]。
但是到了动态规划 思路就不一样了
是以子序列的结束节点为基准,
如: 以 b 为结束点的所有子序列: [a , b] [b]
以 c 为结束点的所有子序列: [a, b, c] [b, c] [ c ]。
这个题就是这个思路
思路说完了上代码
function maxSubArray2 ( nums ) {
if (!nums.length) {
return;
};
// 在每一个扫描点计算以该点数值为结束点的子数列的最大和(正数和)。
let max_ending_here = nums[0];//记录当前最大
let max_so_far = nums[0];//记录全局最大
for (let i = 1; i < nums.length; i ++ ) {
**// 以每个位置为终点的最大子数列 都是基于其前一位置的最大子数列计算得出,**
max_ending_here = Math.max ( nums[i], max_ending_here + nums[i]);
//判断是当前值大还是当前的最大子数列加当前值大
max_so_far = Math.max ( max_so_far, max_ending_here);
//更新全局最大
};
return max_so_far;
};
代码优化
class maxSubArray = function(nums) {
let ans = nums[0];
let sum = 0;
for(let num of nums) {
// if(sum > 0) { 可以写成这样
if(sum + num > num ){
sum = sum + num;
} else {
sum = num;
}
ans = Math.max(ans, sum);
}
return ans;
}
第二块代码和 第一块代码 思路实现是完全一样的,对于这个 if (sum > 0 )
是 if(sum + num > num )两边约去num得来
思路原作者:lao-hu-8
链接:https://leetcode-cn.com/problems/maximum-subarray/solution/xiang-xi-jie-du-dong-tai-gui-hua-de-shi-xian-yi-li/