任意子数组和的绝对值的最大值【LC1749】
给你一个整数数组
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
。
和这两题很像,都是通过前面两种不同的状态转移过来的,删除一次得到子数组最大和&访问数组中的位置使分数最大
-
思路:dp
-
由于所求为子数组和的绝对值,某个子数组和
nums[0,i-1]
可能为负数或者正数,如果nums[i]
与前一子数组的正负值相同,那么取绝对值后的结果将增大。因此需要记录以nums[i]
结尾的最小负数和以及最大正数和 -
定义dp状态:使用 d p [ i ] [ 0 / 1 ] dp[i][0/1] dp[i][0/1]记录以
nums[i]
结尾的最小负数和以及最大正数和 -
状态转移:
都由
nums[i]
与前一个状态相加得到,需要注意的是负数和最大为0,正数和最小为0
d p [ i ] [ 0 ] = m i n ( d p [ i − 1 ] [ 0 ] , 0 ) d p [ i ] [ 1 ] = m a x ( d p [ i − 1 ] [ 1 ] , 0 ) dp[i][0]=min(dp[i-1][0],0)\\ dp[i][1]=max(dp[i-1][1],0) dp[i][0]=min(dp[i−1][0],0)dp[i][1]=max(dp[i−1][1],0) -
初始状态均为0
-
-
实现
使用变量记录
class Solution { public int maxAbsoluteSum(int[] nums) { int res = 0, neg = 0, pos = 0; int n = nums.length; for (int i = 0; i < n; i++){ neg = Math.min(0, neg + nums[i]);// 以nums[i]结尾的和为负数的子数组和 pos = Math.max(0, pos + nums[i]);// 以nums[i]结尾的和为正数的子数组和 res = Math.max(res, Math.max(-neg, pos)); } return res; } }
- 复杂度
- 时间复杂度: O ( n ) \mathcal{O}(n) O(n)
- 空间复杂度: O ( 1 ) \mathcal{O}(1) O(1)
- 复杂度