这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战
前言
关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!
题目描述
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。
示例 1:
输入:nums = [-2,1,-3,4,-1,2,1,-5,4]
输出:6
解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。
示例 2:
输入:nums = [1]
输出:1
示例 3:
输入:nums = [0]
输出:0
示例 4:
输入:nums = [-1]
输出:-1
示例 5:
输入:nums = [-100000]
输出:-100000
链接:leetcode-cn.com/problems/ma…
题解
-
暴力搜索. 暴力搜索很好理解, 题目要求找到连续子数组的最大和, 那么我们可以从数组第一个元素起, 依次找出所有的相邻子数组, 求和并将最大的和保存下来. 具体见代码.
时间复杂度 O(n²), 空间复杂度 O(n).
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubArray = function(nums) {
// 初始化为 最小值
let ans = - Number.MAX_VALUE
const n = nums.length
let curr;
for (let i = 0; i < n; ++i) {
// 每次重新开始
curr = 0
for (let j = i; j < n; ++j) {
curr += nums[j]
ans = Math.max(curr, ans)
}
}
return ans
};
-
动态规划. 暴力解法中, 我们是从 0 位置开始, 找出以 0 位置为左边界的所有连续数组, 保存其中的最大值, 然后在从 1 位置开始, 找出以 1 位置为左边界的所有连续数组, 保存其中的最大值... 其实, 对于这种类型的问题, 我们一般都可以往动态规划的方面来想. 我自己的方法是, 倒着思考, 什么意思呢? 对于这个问题, 就是以 i 元素为右边界, 找出以 i 为结尾的连续子数组的最大值, 如何找呢, 首先假设以 i - 1 元素为右边界的连续子数组的最大值为 x, 那么以 i 元素为右边界的连续子数组的最大值为 max(x + nums[i], nums[i]) 这个很好想清楚, 要么是和 i 之前的连续子数组组成更大的子数组, 要么就是自己独立为更大的子数组. 想到这一步, 其实解法就已经很清晰了.
因为以第 0 位为右边界的子数组的最大值只能为 nums[0], 所以递推下去以第 1 位为右边界的子数组的最大和为 max(nums[0]+nums[1], nums[1]), ... , 这样我们就能得到每个 i 位置上的以它为右边界的最大值, 然后再找出最大的一个即可. 具体见如下代码.
时间复杂度 O(n), 空间复杂度 O(1)
/**
* @param {number[]} nums
* @return {number}
*/
var maxSubArray = function(nums) {
for (let i = 1; i < nums.length; ++i) {
nums[i] = Math.max(nums[i-1]+nums[i], nums[i])
}
let res = Math.max(...nums)
return res
};