1.题目要求:任意给出一个整数的数组,求出元素和最大的子数组的和。要求时间复杂度为n。
2.解析题目要求:
要求出一个数组的最大子数组和,若要求时间复杂度为n²,则可一一求出,再求其最大值,利用两次循环即可。但是若要求时间复杂度为n,只能进行一次遍历,这便是难点所在。关键点在于负数,若全为正数,那么显然最大子数组就是数组本身,所以负数便是分割点,例如,随便列举连续的数组元素1,3,-1,……显然前两个数加上一个负数之后数组和变小,但是这并不能证明前两个数就可以从-1这里断开因为1+3-1>0,所以需要继续向后相加,例如若第四个数为2,显然1+3-1+2>1+3;所以只有当向后加到和小于0时才能在那个负数的地方断开。
3.编程思路:
从第一个正数开始依次往后相加(若全为负数最大子数组和就是最大的那个负数) 相加后会遇到三种情况 (1)max+a[i]>=max 此时可以得知a[i]为正数,可以继续往后相加 (2)max+a[i]<=0 此时可以证明a[i]不但是负数,也是分割点,下一组最大数组和应从i后面第一个大于0的数开始 (3)若max+a[i]>0&&max+a[i]<max,可以得知a[i]<0,但是不能判断此负数是不是断点,所以需要继续向后加,有后面的数决定,知道加到出现情况(1)或(2)或结束即可判断a[i]是否为分割点。(此处需要一个中间变量暂存a[i]之前的最大值)
4.源代码:
public class MaxIntArray { public static void main(String [] args){ int a[]={2,4,-5,7,3,-9,-2,9,9,-1}; int Max[]=new int[10]; Max[0] = 0; int i = 0;//数组下标 int j = 0;//最大值数组下标 int temp=0;//中间变量 while(i<a.length){ if(temp+a[i]>=Max[j]) { temp=temp+a[i]; Max[j]=temp; i++; } else if(temp+a[i]<Max[j]&&temp+a[i]>0) { temp=temp+a[i]; i++; } else if(temp+a[i]<=0) { i++; j++; Max[j]=0; temp=0; } } int max = Max[0]; for(int k=0;k<=j;k++){ if(Max[k]>max) { max=Max[k]; } } /*System.out.println(j); for(int k=0;k<=j;k++){ System.out.println(Max[k]); }*/ System.out.println("最大子数组和为"+max); } }
5.运行结果截图:
算法很关键!有一个灵活的大脑引导出一个简洁的算法就能节省大量程序运行内存和编程量!