最大子序列的问题描述:给定一个原数组,求出其连续子数组的最大和
之前有总结过,但是在看其他书的时候发现,大多数书的第一个范例就是最大子序列和,所以完整版。
一、 穷举式的例举出所有可能并选择
时间复杂度:O(n^3)
分析:使用for循环进行嵌套,例出所有的可能性,进行计算 ,最后选出最大的值
代码如下:
package code;
import java.util.Scanner;
public class Max1 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int k=sc.nextInt();
int[] arr=new int[k];
for(int i=0;i<k;i++) {
arr[i]=sc.nextInt();
}
System.out.println(MaxSum(k,arr));
}
public static int MaxSum(int n,int[] arr) {
int ThisSum,MaxSum;
MaxSum=0;
for(int i=0;i<n;i++) {
for(int j=i;j<n;j++) {
ThisSum=0;
for(int l=i;l<=j;l++) {
ThisSum+=arr[l];
}
if(ThisSum>MaxSum) {
MaxSum=ThisSum;
}
}
}
return MaxSum;
}
}
二、照比上一种方法的进步
时间复杂度:Q(n^2)
分析:想照比上一方法,减少一个FOR循环所造成的重复计算
代码如下:
package code;
import java.util.Scanner;
public class Max2 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int k=sc.nextInt();
int[] arr=new int[k];
for(int i=0;i<k;i++) {
arr[i]=sc.nextInt();
}
System.out.println(MaxSum(k,arr));
}
public static int MaxSum(int n,int[] arr) {
int MaxSum,ThisSum;
MaxSum=0;
for(int i=0;i<n;i++) {
ThisSum=0;
for(int j=i;j<n;j++) {
ThisSum+=arr[j];
if(ThisSum>MaxSum) {
MaxSum=ThisSum;
}
}
}
return MaxSum;
}
}
三、使用递归的分治策略
时间复杂度:O(nlogn)
分析:将问题分成两个大致相等的子问题,然后递归地对他们求解,这是“分部分”,然后“治部分”就是将两个子问题的解合并到一起并可能再做一些商量的附加工作从而得到整个问题的解。——《数据结构与算法分析C语言描述》
代码如下:
package code;
import java.util.Scanner;
public class Max3 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int k=sc.nextInt();
int[] arr=new int[k];
for(int i=0;i<k;i++) {
arr[i]=sc.nextInt();
}
System.out.println(MaxSum(arr,0,k-1));
}
public static int MaxSum(int[] arr,int left,int right) {
int MaxLeftSum,MaxRightSum;
int ThisLeftSum,ThisRightSum;
int MaxCenterLeftSum,MaxCenterRightSum;
if(left==right) {
return arr[left];
}
int center=(left+right)/2;
MaxLeftSum=MaxSum(arr,left,center);
MaxRightSum=MaxSum(arr,center+1,right);
ThisLeftSum=0;
MaxCenterLeftSum=0;
for(int i=center;i>=left;i--) {
ThisLeftSum+=arr[i];
if(ThisLeftSum>MaxCenterLeftSum) {
MaxCenterLeftSum=ThisLeftSum;
}
}
ThisRightSum=0;
MaxCenterRightSum=0;
for(int j=center+1;j<=right;j++) {
ThisRightSum+=arr[j];
if(ThisRightSum>MaxCenterRightSum) {
MaxCenterRightSum=ThisRightSum;
}
}
return Max(MaxLeftSum,MaxRightSum,MaxCenterLeftSum+MaxCenterRightSum);
}
public static int Max(int a,int b,int c) {
int max=0;
if(a<b) {
max=b;
if(max<c) {
max=c;
}
}else {
if(a<c) {
max=c;
}else {
max=a;
}
}
return max;
}
}
四、联机算法(扫描法)
时间复杂度:O(n)
分析:只对数据进行一次扫描,一旦arr[i]被读入并进行过判断以后就不再使用这个数据,所以不再需要对这个数据进行记忆。
代码如下:
package code;
import java.util.Scanner;
public class Max4 {
public static void main(String[] args) {
Scanner sc=new Scanner(System.in);
int k=sc.nextInt();
int[] arr=new int[k];
for(int i=0;i<k;i++) {
arr[i]=sc.nextInt();
}
System.out.println(MaxSum(arr,k));
}
public static int MaxSum(int[] arr,int n) {
int MaxSum=0;
int ThisSum=0;
for(int i=0;i<n;i++) {
ThisSum+=arr[i];
if(ThisSum>MaxSum) {
MaxSum=ThisSum;
}else {
if(ThisSum<0) {
ThisSum=0;
}
}
}
return MaxSum;
}
}