暴力枚举
/**
* 暴力枚举的方式 时间复杂度O(n^3)
*
* @param array 输入
* @return 最大子数组的和的值
*/
public static int forceMaxSubArray(int[] array) {
int lenght = array.length;
int maxvalue = Integer.MIN_VALUE;
for (int i = 0; i < lenght; i++) {
for (int j = i; j < lenght; j++) {
int sum = 0;
for (int k = i; k <=j; k++) {
sum += array[k];
}
if (sum > maxvalue) {
maxvalue = sum;
}
}
}
return maxvalue;
}
优化的暴力枚举
/**
* 优化的暴力枚举 时间复杂度O(n^2)
*
* @param array 输入
* @return 最大子数组的和的值
*/
public static int optimizeForceSubArray(int[] array) {
int lenght = array.length;
int maxvalue = Integer.MIN_VALUE;
for (int i = 0; i < lenght; i++) {
int sum = 0;
for (int j = i; j < lenght; j++) {
// 保存 j 前面的子数组和 避免重复计算
sum += array[j];
if (sum > maxvalue) {
maxvalue = sum;
}
}
}
return maxvalue;
}
分治法
/**
* 分治法 时间复杂度 O(n*log^n)
*
* @param array 输入
* @param left 左边界
* @param right 右边界
* @return 最大子数组的值
*/
public static int divideMaxSubArray(int[] array, int left, int right) {
if (left == right) {
return array[left];
} else {
int mid = (left + right) / 2;
// 左半边最大子数组和
int leftMaxValue = divideMaxSubArray(array, left, mid);
// 右半边最大子数组和
int rightMaxValue = divideMaxSubArray(array, mid + 1, right);
// 跨中间的最大子数组和
int midMaxValue = crossMidValue(array, left, right);
return max(leftMaxValue, rightMaxValue, midMaxValue);
}
}
/**
* 计算跨中间点的最大数组
*
* @param array 输入
* @param left 左边界
* @param right 右边界
* @return 跨中间节点最大子数组的值
*/
private static int crossMidValue(int[] array, int left, int right) {
int leftValue = Integer.MIN_VALUE;
int mid = (left + right) / 2;
int sum = 0;
/*
* 这里左边的范围必须和上面一样 left ~ mid
*/
for (int i = mid ; i >= left; i--) {
// 记录下每次累加的数组和
sum += array[i];
// 如果更大就更新
if (sum > leftValue) {
leftValue = sum;
}
}
int rightValue = Integer.MIN_VALUE;
sum = 0;
/*
* 这里左边的范围必须和上面一样 mid+1 ~ right
*/
for (int i = mid + 1; i <= right; i++) {
// 记录下每次累加的数组和
sum += array[i];
// 如果更大就更新
if (sum > rightValue) {
rightValue = sum;
}
}
// 返回跨越中间的最大数组值 ------ 左边加右边
return leftValue + rightValue;
}
/**
* 返回三个数的最大值
*
* @param leftMaxValue 左数组的最大值
* @param rightMaxValue 右数组最大值
* @param midMaxValue 跨中间的最大值
* @return 最大值
*/
private static int max(int leftMaxValue, int rightMaxValue, int midMaxValue) {
return Math.max(Math.max(leftMaxValue, rightMaxValue), midMaxValue);
}
动态规划
/**
* 动态规划 时间复杂度O(n)
* @param array 输入的数组
*/
private static void getSumOfSubArray05(int[] array) {
int n = array.length;
// 保存最大子数组的和
int[] ev = new int[n];
// 保存最大子数组的起始下标
int[] iv = new int[n];
// 最大子数组的结束下标
int endIndex = Integer.MIN_VALUE;
int max = Integer.MIN_VALUE;
//初始化
ev[0] = array[0];
iv[0] = array[0];
ev[n - 1] = array[n - 1];
for (int i = 1; i < n; i++) {
if (ev[i - 1] + array[i] > array[i]){
ev[i] = ev[i - 1] + array[i];
iv[i] = iv[i - 1];
}else {
ev[i] = array[i];
iv[i] = i;
}
if (ev[i] > max){
max = ev[i];
endIndex = i;
}
}
System.out.println(Arrays.toString(ev));
// 取出数组中最大的数
System.out.println("最大子数组之和为:" + Arrays.stream(ev).max().getAsInt());
System.out.println("范围是:["+iv[endIndex]+"~"+endIndex+"]");
}