1749. 任意子数组和的绝对值的最大值
给你一个整数数组 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.length <= 105
-104 <= nums[i] <= 104
分析
最大子数组和的变式,可以求处最大子数组和和最小子数组和,然后取绝对值的max
代码
typedef long long LL;
class Solution {
public:
const static int N = 1e5 + 5, INF = 0x3f3f3f3f;
int dp1[N], dp2[N];
int maxAbsoluteSum(vector<int>& nums) {
int n = nums.size();
int res = 0;
dp1[0] = -INF;
dp2[0] = INF;
for(int i = 1; i <= n; i ++ ) {
dp1[i] = max(nums[i - 1], dp1[i - 1] + nums[i - 1]);
dp2[i] = min(nums[i - 1], dp2[i - 1] + nums[i - 1]);
res = max(res, abs(dp1[i]));
res = max(res, abs(dp2[i]));
}
return res;
}
};
1191. K 次串联后最大子数组之和
给定一个整数数组 arr
和一个整数 k
,通过重复 k
次来修改数组。
例如,如果 arr = [1, 2] , k = 3
,那么修改后的数组将是 [1, 2, 1, 2, 1, 2]
。
返回修改后的数组中的最大的子数组之和。注意,子数组长度可以是 0
,在这种情况下它的总和也是 0
。
由于 结果可能会很大,需要返回的 109 + 7
的 模 。
数据范围
1 <= arr.length <= 105
1 <= k <= 105
-104 <= arr[i] <= 104
分析
分类讨论,两种情况,对于k=1的情况,直接在长度为n的数组上做一次子数组最大和,对于k>1的情况,可能会出现起点和终点不在同一个区间内,因此需要对数组进行复制,而对于中间是否需要加上一整段区间,只需要看数组的和是否为正数,若是正数,则一定可以将整段区间插入到起点和终点之间。
代码
typedef long long LL;
class Solution {
public:
const static LL N = 1e5 + 5, INF = 0x3f3f3f3f, mod = (LL)1e9 + 7;
LL res = 0;
LL dp[2 * N];
LL kConcatenationMaxSum(vector<int>& arr, int k) {
int n = arr.size();
LL sum = 0;
for(int i = 0; i < n; i ++ ) {
sum += arr[i];
sum %= mod;
}
dp[0] = 0;
for(int i = 1; i <= n * (k > 1 ? 2 : 1); i ++ ) {
dp[i] = max((LL)0, dp[i - 1] + (LL)arr[(i - 1) % n]);
if(sum > 0 && k >= 2) res = max(res, dp[i] + sum * (k - 2) % mod);
else res = max(res, dp[i]);
dp[i] %= mod;
res %= mod;
}
return res % mod;
}
};