给定一个长度为 n
的环形整数数组 nums
,返回 nums
的非空 子数组 的最大可能和 。
环形数组意味着数组的末端将会与开头相连呈环状。形式上, nums[i]
的下一个元素是 nums[(i + 1) % n]
, nums[i]
的前一个元素是 nums[(i - 1 + n) % n]
。
子数组 最多只能包含固定缓冲区 nums
中的每个元素一次。形式上,对于子数组 nums[i], nums[i + 1], ..., nums[j]
,不存在 i <= k1, k2 <= j
其中 k1 % n == k2 % n
。
示例 1:
输入: nums = [1,-2,3,-2]
输出: 3
解释: 从子数组 [3] 得到最大和 3
示例 2:
输入: nums = [5,-3,5]
输出: 10
解释: 从子数组 [5,5] 得到最大和 5 + 5 = 10
示例 3:
输入: nums = [3,-2,2,-3]
输出: 3
解释: 从子数组 [3] 和 [3,-2,2] 都可以得到最大和 3
提示:
n == nums.length
1 <= n <= 3 * 104
-3 * 104 <= nums[i] <= 3 * 104
题解:
/**
* @description: 取反 TC:O(n) SC:O(1)
* @author: JunLiangWang
* @param {*} nums 给定数组
* @return {*}
*/
function negate(nums) {
/**
* 本题与53.最大子数组和有些相似,但此处为环形数组,
* 环形数组最大子数组和与一般数组的最大子数组和不同
* 的地方在于环形数组最大子数组元素可能存在首尾两端,
* 如下:
* 环形数组最大子数组可能: M M M * * * * M M
*
* 其实我们可以换一种思路,上述 * * * * 是否就是数组中
* 最小子数组和呢?数组总和-最小子数组和,不就是首尾
* 两端最大子数组和的情况吗?
*
* 因此环形数组最大子数组和则等于:
* Max(数组总和-最小子数组和,最大子数组和)
*
* 分别对应以下两种情况:
* 1.最大元素处于首位两端:M M M * * * * M M M
* 2.最大元素连续: * M M M M M * * * *
*
*/
// 记录数组最大子数组和
let max = nums[0],
// 记录数组最小子数组和
min = nums[0],
// 记录数组总和
sum = 0,
// 当前连续元素最大总和
sumMaxElement = 0,
// 当前连续元素最小总和
sumMinElement = 0
// 遍历数组元素
nums.forEach((val) => {
// 计算数组最大子数组和
sumMaxElement = Math.max(sumMaxElement + val, val)
max = Math.max(max, sumMaxElement)
// 计算数组最小子数组和
sumMinElement = Math.min(sumMinElement + val, val)
min = Math.min(min, sumMinElement)
sum += val
})
// 如果数组最大子数组和小于等于0,证明数组总和也小于0
// 因此直接返回max,否则比较
return max > 0 ? Math.max(max, sum - min) : max
}