最大子序列和的四种方式

最大子序列的问题描述:给定一个原数组,求出其连续子数组的最大和

之前有总结过,但是在看其他书的时候发现,大多数书的第一个范例就是最大子序列和,所以完整版。

一、 穷举式的例举出所有可能并选择

时间复杂度: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;
}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值