算法题讲解
真题描述:
给你一个整数数组 nums
。一个子数组 [numsl, numsl+1, ..., numsr-1, numsr]
的 和的绝对值 为 abs(numsl + numsl+1 + ... + numsr-1 + numsr)
。
请你找出 nums
中 和的绝对值 最大的任意子数组(可能为空),并返回该 最大值 。
abs(x)
定义如下:
- 如果
x
是负整数,那么abs(x) = -x
。 - 如果
x
是非负整数,那么abs(x) = x
。
示例1:
输入: nums = [1,-3,2,3,-4]
输出: 5
解释: 子数组 [2,3] 和的绝对值最大,为 abs(2+3) = abs(5) = 5 。
示例2:
输入: nums = [2,-5,1,-4,3,-2]
输出: 8
解释: 子数组 [-5,1,-4] 和的绝对值最大,为 abs(-5+1-4) = abs(-8) = 8 。
思路分析
题目让我们求子数组最大绝对值,我们可以把他转化为求最大子数组和 以及「最小子数组和的绝对值(相反数)」
方法一
代码
var maxAbsoluteSum = function(nums) {
let currentMax = 0;
let maxSum = 0;
let currentMin = 0;
let minSum = 0;
for (let i = 0; i < nums.length; i++) {
// 计算当前位置前缀和
currentMax += nums[i];
currentMin += nums[i];
// 更新最大和与最小和
if (currentMax > maxSum) {
maxSum = currentMax;
}
if (currentMin < minSum) {
minSum = currentMin;
}
// 如果当前位置前缀和为负数,则将其重置为零
if (currentMax < 0) {
currentMax = 0;
}
if (currentMin > 0) {
currentMin = 0;
}
}
//Math.abs(maxSum):这部分计算了 maxSum 的绝对值
//Math.abs(minSum):这部分计算了 minSum 的绝对值
//Math.max() 函数用于比较这两个绝对值,返回其中较大的一个
return Math.max(Math.abs(maxSum), Math.abs(minSum));
};
初始化变量:
- currentMax 和 currentMin 用于存储当前位置前缀和的最大值和最小值。
- maxSum 和 minSum 分别用于记录全局最大和与最小和。
使用循环遍历数组:
- 在每次循环中,将当前元素加到前缀和中,并更新当前位置前缀和的最大值(currentMax += nums[i]) 和 最小值(currentMin += nums[i])。
更新全局最大和与最小和:
- 如果当前位置前缀和 (currentMax) 大于全局最大和 (maxSum),则更新为新的较大值。
- 如果当前位置前缀和 (currentMin) 小于全局最小和 (minSum),则更新为新的较小值。
重置负数前缀之后:
- 若当前位置前缀之 (currentMax) 是负数,则将其重置为零。
- 若当前位置正数之 (currentMin) 是正数,则将其重置为零。
返回结果:
- 使用 Math.abs() 函数计算出 maxSum 和 minSum 的绝对值,并通过 Math.max() 函数返回其中较大者作为结果。
总结
该代码通过不断累加连续子数组元素并动态更新计算当前位置的最大和与最小和,同时将负数前缀之重置为零。然后返回全局最大和与最小和的绝对值中较大者作为结果。