题目:
对于一个给定的数组A,求 A中连续子数组,使得该数组的和最大
例如:
A:1, -2, 3, 10, -4, 7, 2, -5
结果:3 10 -4 7 2
方法:
- 暴力法 — 遍历求A的所有子数组,求和最大的
- 分治法:
数组的和最大那个数组只会出现在以下三种情况中:
a. 存在于数组下标从0到mid中,其中mid为数组长度(length)的一半
b. 存在于数组下标从mid到length中
c. 跨越数组下标mid,且下标mid在和最大数组中- 动态规划
代码:
public class 最大连续子数组 {
public static void main(String[] args) {
int[] array = new int[] { 1, -2, 3, 10, -4, 7, 2, -5 };
// 1.暴力法--遍历
// f1(array);
// 2. 分治法--先分然后在处理
// int res = f2(array, 0, array.length - 1);
// 3. 动态规划
int res = f3(array, 0, array.length - 1);
System.out.println("子数组:");
for (int i = from; i <= to; i++) {
System.out.print(array[i] + " ");
}
System.out.println("\n和:\n" + res);
}
// 3. 动态规划
// s[k+1] = max ( s[k]+a[k+1], a[k+1] ) 要么继续连续,要么断开
private static int f3(int[] array, int start, int end) {
int sum = array[start];
for (int i = start + 1; i < end; i++) {
if (sum < 0) {
sum = array[i];
from = i;
} else {
sum += array[i];
to = i;
}
}
return sum;
}
private static int from;
private static int to;
// 2. 分治法
private static int f2(int[] array, int start, int end) {
if (start == end) {
return array[start];
}
int mid = (start + end) / 2;
int m1 = f2(array, start, mid); // 最大值在前一半
int m2 = f2(array, mid + 1, end); // 最大值在后一半
int mf = array[mid];
int sum = 0;
for (int i = mid; i >= start; i--) {
sum += array[i];
if (sum > mf) {
mf = sum;
from = i;
}
}
int mb = array[mid + 1];
sum = 0;
for (int i = mid + 1; i <= end; i++) {
sum += array[i];
if (sum > mb) {
mb = sum;
to = i;
}
}
int m3 = mf + mb;
int res = 0;
if (m1 > m2) {
res = m1;
} else {
res = m2;
}
if (res < m3) {
res = m3;
}
return res;
}
// 暴力法
private static void f1(int[] array) {
if (array == null || array.length <= 0) {
return;
}
if (array.length == 1) {
System.out.println(array[0]);
}
int max = array[0];
int start = 0;
int end = 0;
for (int i = 0; i < array.length; i++) {
for (int j = i; j < array.length; j++) {
int sum = 0;
for (int k = i; k <= j; k++) {
sum += array[k];
}
if (sum > max) {
max = sum;
start = i;
end = j;
}
}
}
for (int i = start; i <= end; i++) {
System.out.print(array[i] + " ");
}
System.out.println("\n" + max);
}
}
运行结果:
子数组:
3 10 -4 7 2
和:
18