题目链接
https://leetcode.com/problems/maximum-absolute-sum-of-any-subarray/
题目描述
给定整数数组nums,定义子序列的absolute sum为子序列各元素相加后的绝对值。返回nums所有子序列的最大absolute sum。
示例
输入:nums = [2,-5,1,-4,3,-2]
输出:8
和的绝对值最大的子序列为[-5,1,-4]
解决思路一
这道题可看作【leetcode-Python】-Dynamic Programming -53. Maximum Subarray题目的扩展,一个子序列和的绝对值最大有三种可能:该子序列和为最大值;子序列和为最小值。在Kadane's Algorithm的基础上进行修改,循环到第j步时,更新以nums[j]为结尾的最大值、最小值,并更新待返回的和的最大绝对值。
解决思路一Python实现
class Solution:
def maxAbsoluteSum(self, nums: List[int]) -> int:
maxSum = 0
minSum = 0
absmaxSum = 0
for i in range(len(nums)):
maxSum = max(nums[i],maxSum + nums[i])
minSum = min(nums[i],minSum + nums[i])
absmaxSum = max(absmaxSum,abs(maxSum),abs(minSum)) #max()可以用于多个参数取最大值
return absmaxSum
时间复杂度和空间复杂度
由于只循环一次,时间复杂度为O(n); 算法执行所需开辟的内存空间不会随着n的改变而改变,因此空间复杂度为O(1)。
解决思路二
可以通过对前缀和稍做修改来解决这个问题。对于数组x和它的前缀和数组y,有y[n] = x[0] + x[1] + ... + x[n]。因此有子序列和的绝对值abs(x[i]+x[i+1]+...+x[j]) = abs(y[j]-y[i-1]),即子序列和的绝对值等于一个前缀和减去另一个前缀和。因此子序列和的最大绝对值有三种情况:
设y[p] = max(y), y[q] = min[y]。
如果y[p]大于0,y[q]小于0,那么和的绝对值最大的子序列索引区间为[p+1,q](p<q)或[q+1,p](p>q);
如果y[q]大于0,即最大前缀和与最小前缀和都大于0时,和的绝对值最大的子序列索引区间为[0,p],最大绝对值为最大前缀和;
如果y[p]小于0,即最大前缀和与最小前缀和都小于0时,和的绝对值最大的子序列索引区间为[0,q],最大绝对值为abs(最小前缀和)
解决思路二Python实现
在代码中可以初始化最大前缀和与最小前缀和为0;这样最大前缀和不会出现负数,最小前缀和不会出现正数,将返回格式统一为max-min。
class Solution:
def maxAbsoluteSum(self, nums: List[int]) -> int:
max_prefix_sum = 0
min_prefix_sum = 0
prefix_sum = 0
for i in range(len(nums)):
prefix_sum += nums[i]
max_prefix_sum = max(max_prefix_sum,prefix_sum)
min_prefix_sum = min(min_prefix_sum,prefix_sum)
return max_prefix_sum - min_prefix_sum
时间复杂度和空间复杂度
只循环一次,时间复杂度为O(n); 算法执行所需开辟的内存空间不会随着n的改变而改变,因此空间复杂度为O(1)。