问题描述
给定一个数组arr,返回子数组的最大累加和
例: arr = [1,-2,3,5,-2,6,-1];所有子数组中[3,5,-2,6]可以累加出最大的和为12,所以返回12。
算法思路
注:首先解释一下什么是子数组?即一段连续的数组的切片
解法一:暴力破解O(n^2)
双重for循环,计算每个子数组的累加和,记录其中最大的累加和。
public class _05_子数组的最大的和 {
public static void main(String[] args) {
int[] arr = {1,-2,3,5,-2,6,-1};
findByForce(arr);
}
//暴力破解法 O(n^2)
static void findByForce(int[] arr) {
int maxSum = arr[0];
for (int i = 0;i < arr.length;i++) {
int sum = arr[i];
int maxOfI = sum;
for (int j = i+1;j < arr.length;j++) {
sum += arr[j];
if (sum > maxOfI) {
maxOfI = sum;
}
}
if (maxOfI > maxSum) {
maxSum = maxOfI;
}
}
System.out.println(maxSum);
}
}
程序的运行结果:12
解法二:递推法O(n)
负数舍弃,正数保留:
从左到右一遍遍历,顺序累加,只要累加和小于0就直接舍弃左边的,从下一个开始重新累加,不断更新更大的非负的累加和。
public class _05_连续子数组的最大的和 {
public static void main(String[] args) {
int[] arr = {1,-2,3,5,-2,6,-1};
findByDp(arr);
}
//递推法 O(n)
static void findByDp(int[] arr) {
int sumI = arr[0];
int maxSum = sumI;
for (int i=1;i < arr.length;i++) {
if (sumI >= 0) {//左子表的最大和为正,继续向后累加
sumI += arr[i];
} else {//左子表的最大和为负,丢弃左边的,定义右边的第一个为最大和,继续向后加
sumI = arr[i];
}
if (sumI > maxSum) {
maxSum = sumI;
}
}
System.out.println(maxSum);
}
}
程序的运行结果:12