K 次串联后最大子数组之和
难度:
标签:
题目描述
代码结果
运行时间: 58 ms, 内存: 27.6 MB
/*
题目思路:
1. 使用Java Stream对数组进行处理。
2. 需要对流的元素进行聚合计算。
3. 使用Stream API来实现Kadane算法。
4. 需要考虑数组和前缀和、后缀和以及数组整体和的处理。
*/
import java.util.Arrays;
public class Solution {
public int kConcatenationMaxSum(int[] arr, int k) {
int MOD = 1000000007;
long maxSubarraySum = kadane(arr);
if (k == 1) {
return (int)(maxSubarraySum % MOD);
}
long prefixSum = 0, suffixSum = 0, maxPrefixSum = 0, maxSuffixSum = 0;
long totalSum = Arrays.stream(arr).asLongStream().sum();
long currentSum = 0;
for (int x : arr) {
currentSum += x;
prefixSum = Math.max(prefixSum, currentSum);
}
currentSum = 0;
for (int i = arr.length - 1; i >= 0; i--) {
currentSum += arr[i];
suffixSum = Math.max(suffixSum, currentSum);
}
if (totalSum > 0) {
return (int)((maxPrefixSum + maxSuffixSum + (totalSum * (k - 2))) % MOD);
} else {
return (int)(Math.max(maxPrefixSum + maxSuffixSum, maxSubarraySum) % MOD);
}
}
private long kadane(int[] arr) {
return Arrays.stream(arr)
.mapToLong(x -> x)
.collect(() -> new long[2], (a, b) -> {
a[0] = Math.max(0, a[0] + b);
a[1] = Math.max(a[1], a[0]);
}, (a, b) -> {
a[0] = Math.max(a[0], b[0]);
a[1] = Math.max(a[1], b[1]);
})[1];
}
}
解释
方法:
该题解利用了Kadane算法来找出最大的子数组和,同时考虑了数组被重复k次时的不同情况:
1. 当数组总和为正时,最大和可能包括中间多个完整的数组和两头的部分数组。这种情况下,计算方式为两个数组的最大子数组和加上中间k-2个数组的总和。
2. 当数组总和不为正时,最大子数组和只可能出现在前两个数组内,因为更多的重复只会增加非正的总和。
3. 当k小于或等于2时,不需要考虑多个数组的累加总和,只需计算前k个数组内的最大子数组和。
时间复杂度:
O(n)
空间复杂度:
O(1)
代码细节讲解
🦆
在题解中提到,当数组总和为正时,最大和可能包括中间多个完整的数组和两头的部分数组,能否详细解释这种情况下的计算逻辑和原因?
▷🦆
题解使用了Kadane算法处理至多两倍数组长度,为什么选择遍历两倍数组长度是足够的?是否有可能丢失更长数组中的某些最大子数组和情况?
▷🦆
题解中提到,当k小于或等于2时,只需要计算前k个数组内的最大子数组和,这里的逻辑是否意味着对于所有k > 2的情况,数组总和为负或零时最大子数组和一定为0?
▷🦆
题解中将最终结果模上109 + 7,这一步骤在算法中的作用是什么?为什么这样做是必要的?
▷