# [53] 最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例:
输入: [-2,1,-3,4,-1,2,1,-5,4]
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。
进阶: 如果你已经实现复杂度为 O(n) 的解法,尝试使用更为精妙的分治法求解。
这道题根据leetcode
给的tag
提示,我们有两种解题思路。
# 动态规划解法
一种是利用动态规划的思想
状态转移方程:dp[i] = max(dp[i-1] + nums[i], nums[i])
原始动态规划解法,由于本题不需要回溯子序列索引,因此不需要记录每一步的最大值
var maxSubArray = function(nums) {
const dp = new Array(nums.length).fill(Number.MIN_SAFE_INTEGER);
dp[0] = nums[0];
let sum = nums[0];
for (let i = 1; i < nums.length; i++) {
let temp1 = dp[i - 1] + nums[i];
let temp2 = nums[i];
dp[i] = Math.max(temp1, temp2);
sum = Math.max(sum, dp[i]);
}
return sum;
};
观察dp数组可知,dp[i]仅与dp[i-1]相关,因此完全可以用一个变量替代dp数组,从而节省空间复杂度。(下面的解顺便求了最大子序列)
var maxSubArray = function(nums) {
let dp = nums[0];
let res = nums[0];
let tempArr = [nums[0]];
let resArr = [nums[0]];
for (let i = 1; i < nums.length; i++) {
if (nums[i] < dp + nums[i]) {
dp = nums[i] + dp;
tempArr.push(nums[i]);
} else {
dp = nums[i];
tempArr = [nums[i]];
}
if (res < dp) {
res = dp;
resArr = [...tempArr];
}
}
console.log(resArr);
return res;
};
最后的解如下:
var maxSubArray = function(nums) {
let dp = nums[0];
let sum = nums[0];
for (let i = 1; i < nums.length; i++) {
dp = Math.max(dp + nums[i], nums[i]);
sum = Math.max(sum, dp);
}
return sum;
};
# 分治法
最大子序列和的位置有以下三种情况:
- 考虑中间元素nums[m], 跨越左右两部分,这里从中间元素开始,往左求出后缀最大,往右求出前缀最大, 保持连续性。
- 不考虑中间元素,最大子序列和出现在左半部分,递归求解左边部分最大子序列和
- 不考虑中间元素,最大子序列和出现在右半部分,递归求解右边部分最大子序列和 分别求出三种情况下最大子序列和,三者中最大值即为最大子序列和。
var maxSubArray = function(nums) {
return SubHelper(nums, 0, nums.length - 1);
};
function SubHelper(nums, l, r) {
if (l === r) return nums[l];
let sum = 0;
let leftMax = Number.MIN_SAFE_INTEGER;
let rightMax = Number.MIN_SAFE_INTEGER;
const mid = l + ((r - l) >> 1);
const subLeft = SubHelper(nums, l, mid);
const subRight = SubHelper(nums, mid + 1, r);
for (let i = mid; i >= l; i--) {
sum += nums[i];
if (sum > leftMax) leftMax = sum;
}
sum = 0;
for (let i = mid + 1; i <= r; i++) {
sum += nums[i];
if (sum > rightMax) rightMax = sum;
}
return Math.max(leftMax + rightMax, subLeft, subRight);
}