给你一个整数数组 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 <= nums.length <= 105 -104 <= nums[i] <= 104
进阶:如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的 分治法 求解。
方法一:动态规划 时间复杂度是 O(N),空间复杂度也是 O(N)
var maxSubArray = function(nums) {
let len = nums.length;
if(!len)return 0;
let dp = Array(len);
// dp[i]的定义:nums数组切开,以nums[i]这个元素结尾的子数组,最大连续子数组和
// 想象一下,你知道一个数组的最大连续子数组和为S1,那么如果再让数组里添加一个元素M,那最大的子数组和的值可能是S1+M 或者M(不可能是S1因为结尾的元素必须是nums[i]),
dp[0] = nums[0];
let max = Number.MIN_SAFE_INTEGER;
for(let i = 1; i< len; i++) {
dp[i] = Math.max(nums[i], dp[i-1] + nums[i])
}
for(let i = 0;i < len;i++) {
max = Math.max(max, dp[i])
}
return max;
}
方法二: 分治求解,时间复杂度o(N),空间复杂度o(1)
观察发现,dp[i]的值只跟dp[i-1]有关,那么可以使用滚动更新的方式,可以降低空间复杂度
var maxSubArray = function(nums) {
let len = nums.length;
if(!len) return 0;
let dp_i_1 = nums[0], dp_i_2, max = Number.MIN_SAFE_INTEGER
for(let i = 1; i < len; i++) {
//滚动更新
dp_i_2 = Math.max(dp_i_1 + nums[i], nums[i])//根据dp_i_1计算出dp_i_2
dp_i_1 = dp_i_2 // 把dp2赋值给dp1,往后挪一步
max = Math.max(dp_i_2, max)// 重新计算max
}
return max;
}