问题理解
我们需要在一个整数数组中找到一个长度为 k 的子数组,使得其和最大。如果数组长度恰好为 k,则不进行删除操作。否则,我们可以删除数组中的任意一个元素,然后再找到长度为 k 的子数组,使得其和最大。
数据结构选择
我们可以使用滑动窗口(Sliding Window)来计算子数组的和,这样可以避免重复计算,提高效率。
算法步骤
-
特殊情况处理:如果数组长度
n恰好等于k,直接计算整个数组的和并返回。 -
滑动窗口计算:
- 计算原始数组中所有长度为
k的子数组的和,并记录最大值。 - 对于每个可能删除的元素,重新计算删除该元素后的数组中所有长度为
k的子数组的和,并记录最大值。
- 计算原始数组中所有长度为
-
比较和返回:比较所有情况下的最大和,返回最大值。
优化思路
- 可以预先计算前缀和(Prefix Sum),这样在计算子数组和时可以更快。
- 在删除元素后,利用前缀和快速计算新的子数组和。
代码
public class Main {
public static int solution(int n, int k, int[] nums) {
if (n == k) {
int sum = 0;
for (int num : nums) {
sum += num;
}
return sum;
}
int maxSum = Integer.MIN_VALUE;
// 计算原始数组的前缀和
int[] prefixSum = new int[n + 1];
for (int i = 0; i < n; i++) {
prefixSum[i + 1] = prefixSum[i] + nums[i];
}
for (int i = 0; i < n; i++) {
// 删除第 i 个元素后的子数组和
int sum = 0;
// 使用滑动窗口计算子数组和
for (int start = 0; start <= n - 1 - k; start++) {
if (start <= i && i < start + k) {
// 如果删除的元素在当前窗口内,跳过这个窗口
continue;
}
// 计算子数组和
sum = prefixSum[start + k] - prefixSum[start];
maxSum = Math.max(maxSum, sum);
}
}
return maxSum;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(5, 3, new int[]{2, 1, 3, -1, 4}) == 8);
}
}