翻转增益的最大子数组和
问题描述
给定整数数组,我们称其中连续的 0 个或多个整数为一个子数组,求翻转任一子数组后,新数组中子数组的和的最大值
输入格式
第一行输入为 N,代表数组长度
第二行输入为 N 个整数,依次为数组的每个元素
输出格式
一个整数 K,代表所有可能新数组中子数组的和的最大值
输入样例
5
1 2 3 -1 4
输出样例
10
说明
选择翻转子数组 [-1, 4] 或 [1, 2, 3, -1],新数组分别是 [1, 2, 3, 4, -1] 和 [-1, 3, 2, 1, 4],二者的子数组最大和都是 10
数据范围
50% case:1 <= N <= 100, -100<= arr[i] <= 100
100% case:1 <= N <= 1e6, -100<= arr[i] <= 100
问题理解
我们需要找到一个整数数组中,通过翻转任意一个子数组后,新数组中子数组的和的最大值。
关键点
- 子数组:连续的0个或多个整数。
- 翻转:将子数组中的元素顺序颠倒。
- 最大和:翻转后的新数组中,所有可能的子数组的和的最大值。
解题思路
-
计算原始数组的最大子数组和:
- 使用Kadane算法可以在O(N)时间内计算出原始数组的最大子数组和。
-
计算翻转子数组的影响:
- 翻转一个子数组会影响该子数组及其周围的元素。
- 翻转子数组后,新的子数组和可能会发生变化。
-
考虑翻转的子数组:
- 翻转的子数组可以是任意长度的,从1到N。
- 需要考虑翻转后对整个数组的影响,特别是翻转后子数组的和的变化。
-
计算翻转后的最大子数组和:
- 需要遍历所有可能的翻转子数组,计算翻转后的新数组的最大子数组和。
- 可以通过预处理数组,计算出每个位置翻转后的影响,从而优化计算。
解题代码
public class Main {
public static int solution(int N, int[] data_array) {
//将主数组中的数字求和,判断初始数组和
int originalMaxSum = kadane(data_array);
int maxSumAfterFlip = originalMaxSum;
//遍历数组,找出所有子数组
for (int i = 0; i < N; i++) {
for (int j = i; j < N; j++) {
//翻转当前子数组
int[] flippedArray = flipSubarray(data_array, i, j);
//求出最大子数组和
int flippedMaxSum = kadane(flippedArray);
maxSumAfterFlip = Math.max(maxSumAfterFlip, flippedMaxSum);
}
}
return maxSumAfterFlip;
}
private static int kadane(int[] array) {
int maxSum = array[0];//最大字数组和,初始为a[0]
int curSum = array[0];//当前字数组和
for(int i = 1;i < array.length;i++){
//判断字数组是否为负
if(curSum < 0){
curSum = array[i];//初始化子数组和
}else{
curSum += array[i];
}
if (curSum > maxSum) {
maxSum = curSum;//找出数组最大子数组和
}
}
return maxSum;
}
private static int[] flipSubarray(int[] array, int start, int end) {
int[] flippedArray = array.clone();//复制数组
//判断是否遍历完成,从头到尾交换数字
while (start < end) {
int temp = flippedArray[start];
flippedArray[start] = flippedArray[end];
flippedArray[end] = temp;
start++;
end--;
}
return flippedArray;
}
public static void main(String[] args) {
System.out.println(solution(5, new int[] { 1, 2, 3, -1, 4 }) == 10);
int[] array1 = { -85, -11, 92, 6, 49, -76, 28, -16, 3, -29, 26, 37, 86, 3, 25, -43, -36, -27, 45, 87, 91, 58,
-15, 91, 5, 99, 40, 68, 54, -95, 66, 49, 74, 9, 24, -84, 12, -23, -92, -47, 5, 91, -79, 94, 61, -54,
-71, -36, 31, 97, 64, -14, -16, 48, -79, -70, 54, -94, 48, 37, 47, -58, 6, 62, 19, 8, 32, 65, -81, -27,
14, -18, -34, -64, -97, -21, -76, 51, 0, -79, -22, -78, -95, -90, 4, 82, -79, -85, -64, -79, 63, 49, 21,
97, 47, 16, 61, -46, 54, 44 };
System.out.println(solution(100, array1) == 1348);
}
}
AI搜题给了我解题思路,并且教会了我kadane函数(求数组最大子数组和)。 收获匪浅。