目标
给你一个整数数组 nums 和一个整数 k 。
返回 nums 中一个 非空子数组 的 最大 和,要求该子数组的长度可以 被 k 整除。
示例 1:
输入: nums = [1,2], k = 1
输出: 3
解释:
子数组 [1, 2] 的和为 3,其长度为 2,可以被 1 整除。
示例 2:
输入: nums = [-1,-2,-3,-4,-5], k = 4
输出: -10
解释:
满足题意且和最大的子数组是 [-1, -2, -3, -4],其长度为 4,可以被 4 整除。
示例 3:
输入: nums = [-5,1,2,-3,4], k = 2
输出: 4
解释:
满足题意且和最大的子数组是 [1, 2, -3, 4],其长度为 4,可以被 2 整除。
说明:
- 1 <= k <= nums.length <= 2 * 10^5
- -10^9 <= nums[i] <= 10^9
思路
计算长度能被 k 整除的子数组的最大元素和。
核心点是维护同余前缀和的最小值。
也有网友使用滑窗加动态规划来做,滑窗计算 长度为 k 的子数组和,动态规划累加长度 m * k 的子数组和,这里使用了贪心策略,如果前面的子数组和小于 0,直接重置为 0。
代码
/**
* @date 2025-11-27 9:06
*/
public class MaxSubarraySum3381 {
public long maxSubarraySum(int[] nums, int k) {
int n = nums.length;
long[] prefix = new long[n + 1];
for (int i = 1; i <= n; i++) {
prefix[i] = prefix[i - 1] + nums[i - 1];
}
long[] minPrefix = new long[k];
Arrays.fill(minPrefix, Long.MAX_VALUE / 2);
long res = Long.MIN_VALUE;
for (int i = 0; i <= n; i++) {
int rem = i % k;
res = Math.max(res, prefix[i] - minPrefix[rem]);
minPrefix[rem] = Math.min(minPrefix[rem], prefix[i]);
}
return res;
}
}
性能
