问题描述
小C面对一个由整数构成的数组,他考虑通过一次操作提升数组的潜力。这个操作允许他选择数组中的任一子数组并将其翻转,目的是在翻转后的数组中找到具有最大和的子数组。小C对这个可能性很感兴趣,并希望知道翻转后的数组中可能得到的最大子数组和是多少。
例如,数组是 1, 2, 3, -1, 4。小C可以选择翻转子数组 -1, 4 得到 1, 2, 3, 4, -1 或者翻转 1, 2, 3, -1 得到 -1, 3, 2, 1, 4,在这两种情况下,最大的子数组和都是 10。
备注:子数组 是数组中的一个连续部分。
输入
- N: 数组的长度
- data_array: 一个长度为 N 的整数数组
输出
请你返回执行翻转操作后(也可以选择不翻转),数组中可能获得的最大子数组和。
测试样例
样例1:
输入:
N = 5,data_array = [1, 2, 3, -1, 4]
输出:10
样例2:
输入:
N = 4,data_array = [-3, -1, -2, 3]
输出:3
样例3:
输入:
N = 3,data_array = [-1, -2, -3]
输出:-1
样例4:
输入:
N = 6,data_array = [-5, -9, 6, 7, -6, 2]
输出:15
样例5:
输入:
N = 7,data_array = [-8, -1, -2, -3, 4, -5, 6]
输出:10
这题的基本思路是针对每个数组区间i到j 翻转之后得到新数组 再计算最大子数组和 与当前的最大值进行比较从而更新
public class Solution {
public static int solution(int N, int[] data_array) {
// 计算原始数组的最大子数组和
int originalMax = maxSubArraySum(data_array);
// 将原始数组的最大子数组和作为初始的最大和
int maxSum = originalMax;
for (int i = 0; i < N; i++) {
// 内层循环,遍历数组的结束位置j,j从i开始,这样可以确保子数组的合法性
for (int j = i; j < N; j++) {
// 对从位置i到位置j的子数组进行翻转,得到一个新的数组
int[] newArray = flipSubarray(data_array, i, j);
// 计算新数组的最大子数组和
int newMax = maxSubArraySum(newArray);
// 将新数组的最大子数组和与当前的最大和maxSum进行比较,取较大值更新maxSum
maxSum = Math.max(maxSum, newMax);
}
}
// 返回经过所有可能的子数组翻转后得到的最大子数组和
return maxSum;
}
// 定义一个私有静态方法flipSubarray,用于翻转数组中从start到end的子数组
private static int[] flipSubarray(int[] array, int start, int end) {
// 克隆原始数组,得到一个新的数组,这样不会影响原始数组
int[] newArray = array.clone();
// 使用双指针法翻转子数组,start指向子数组的起始位置,end指向子数组的结束位置
while (start < end) {
// 交换start和end位置的元素
int temp = newArray[start];
newArray[start] = newArray[end];
newArray[end] = temp;
// start指针向后移动一位
start++;
// end指针向前移动一位
end--;
}
// 返回翻转后的新数组
return newArray;
}
// 定义一个私有静态方法maxSubArraySum,用于计算给定数组的最大子数组和
private static int maxSubArraySum(int[] array) {
// 将数组的第一个元素作为当前子数组的和以及全局最大子数组和的初始值
int currentSum = array[0];
int maxSum = array[0];
// 遍历数组,从第二个元素开始
for (int i = 1; i < array.length; i++) {
// 计算当前位置的最大子数组和,要么是当前元素本身,要么是当前元素加上之前的子数组和
currentSum = Math.max(array[i], currentSum + array[i]);
// 将当前位置的最大子数组和与全局最大子数组和进行比较,取较大值更新全局最大子数组和
maxSum = Math.max(maxSum, currentSum);
}
// 返回计算得到的最大子数组和
return maxSum;
}
}
如果考虑优化的话 maxSubArraySum可以采用线段树实现 具体方法可参考力扣