感谢程云老师的分享~下面记录一下用不同方法实现最大字段和
时间复杂度o(n^3)
/*
* 复杂度o(n^3)
* 该算法使用3重循环,将所有子段的和求出,然后求出和最大的*/
public static void sum1(int a[]) {
int ans = Integer.MIN_VALUE;
int mini = 0, maxi = 0;
for (int i = 0; i < a.length; i++) {
for (int j = i; j < a.length; j++) {
int sum = 0;
for (int k = i; k <= j; k++) {
sum += a[k];
// ans=Math.max(ans,sum);
if (sum > ans) {
mini = i;
maxi = j;
ans = sum;
}
}
}
}
System.out.println("ans=" + ans);
System.out.println("mini=" + mini + " max=" + maxi);
}
时间复杂度为o(n^2)
/*时间复杂度为o(n^2)
* 用s[i]记录前i项字段和,i到j的字段和=s[j]-s[i]
* 然后使用两重循环用s[j]-s[i]求出所有子段的和,然后求出其中最大的*/
public static void sum2(int a[]) {
int s[] = new int[a.length];
s[0] = 0;
for (int i = 1; i < a.length; i++) {
s[i] = s[i - 1] + a[i];
}
int ans = Integer.MIN_VALUE;
for (int i = 0; i < a.length; i++) {
for (int j = i; j < a.length; j++) {
int sum = s[j] - s[i];
if (ans < sum)
ans = sum;
}
}
System.out.println("ans=" + ans);
}
时间复杂度为nlogn
/*
* 时间复杂度为nlogn
* 分治方法,从中间划分,最大字段和存在三种情况:左边,右边或既在左又在右侧*/
public static int sum3(int a[], int left, int right) {
if (left == right) {
System.out.println(right);
return a[left];
}
int mid = (left + right) / 2;
System.out.println(mid);
int l_max = sum3(a, left, mid);
int r_max = sum3(a, mid + 1, right);
int lm_max = Integer.MIN_VALUE;
int temp = 0;
for (int i = mid; i >= left; i--) {
temp += a[i];
if (temp > lm_max)
lm_max = temp;
}
int rm_max = Integer.MIN_VALUE;
temp = 0;
for (int i = mid + 1; i <= right; i++) {
temp += a[i];
if (temp > rm_max)
rm_max = temp;
}
int m_max = rm_max + lm_max;
return Math.max(l_max, Math.max(m_max, r_max));
}
时间复杂度为o(n)
*o(n)
* 动态规划
* 动态规划方程:s[i] = max(s[i-1], s[i-1]+a[i]),即比较前i-1个子段和和前i个子段的大小
**/
public static void sum4(int a[]) {
int ans = Integer.MIN_VALUE;
int temp = 0;
for (int i = 0; i < a.length; i++) {
if (temp + a[i] < 0) {
temp = 0;
continue;// continue终端本次循环开始下一次
}
ans = Math.max(ans, temp += a[i]);
}
System.out.print(ans);
}
实例 int a[]={1,2,-4,5,-4,4,6};结果为11