题目描述 - 最大子数组和
给你一个整数数组 nums
,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
子数组 是指数组中的一个连续部分。
示例:
- 输入:
nums = [-2,1,-3,4,-1,2,1,-5,4]
,输出: 6,连续子数组[4,-1,2,1]
的和最大,为 6 - 输入:
nums = [1]
,输出: 1 - 输入:
nums = [5,4,-1,7,8]
,输出: 23
思路分析
- 暴力解法,双重遍历,遍历所有节点开头的所有子序列: 如数组
[a, b, c, d]
,进行循环遍历时,[a]
,[a, b]
,[ a, b, c]
,[ a, b, c, d]
,再从以b
为开头的子序列开始遍历[b] [b, c]...
。
代码实现:
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubArray = function(nums) {
// max 初始值不能为0,要考虑数组有负数数据存在,如数据[-1] 会返回错误
let max = 0;
for(let i=0; i< nums.length; i++){
let sum = 0
for(let j=i; j<nums.length; j++){
sum += nums[j]
sum > max ? max = sum : ""
}
}
return max
};
上面的暴力解法在leetcode上提交之后,毫无疑问,超出了时间限制,我们需要寻找更优解。
-
动态规划
我们假设 dp[ i ] 为以第i个元素结尾且和最大的连续子数组。
对于元素 i,所有以它前面的元素结尾的子数组的长度都已经求得,那么,dp[ i ]=dp[ i-1 ] + arr[ i ]
以第 i 个元素结尾且和最大的连续子数组实际上,要么是以第 i-1 个元素结尾且和最大的连续子数组加上这个元素,要么是只包含第 i 个元素 dp[ i ] = max(dp[i-1] + a[ i ], a[ i ])。
我们可以通过判断 dp[ i-1 ] + a[ i ] 是否大于 a[ i ] 来做选择,而这实际上等价于判断 dp[ i-1 ] 是否大于0。
如下图所示: 代码实现:
/** * @param {number[]} nums * @return {number} */ var 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; };