数组问题之一维最大字段和问题<Java实现>

/**
 * 一维最大字段和问题,约定如果全部元素均是负数,
 * 则最大字段和为0(不选任何元素)。
 * @author Sking
 */
package 数组问题;

public class 一维最大子段和 {

	/**
	 * 暴力遍历求解最大字段和问题
	 * 时间复杂度为O(n^3)
	 * @param a 指定序列
	 * @return 最大字段和
	 */
	  public static int maxSum0(int[] a){
			int n=a.length-1;
			int sum=0;
			for(int i=1;i<=n;i++)
			for(int j=i;j<=n;j++){
				int thissum=0;
				for(int k=i;k<=j;i++)thissum+=a[k];
				if(thissum>sum)
					sum=thissum;
			}
			return sum;
		}
	  
		/**
		 * 改进的暴力遍历求解最大字段和问题
		 * 时间复杂度为O(n^2)
		 * @param a 指定序列
		 * @return 最大字段和
		 */
		public  static int maxSum1(int[] a) {
			int n = a.length - 1;
			int sum = 0;
			for (int i = 1; i <= n; i++) {
				int thissum = 0;
				for (int j = i; j <= n; j++) {
					thissum += a[j];
					if (thissum > sum) {
						sum = thissum;
					}

				}
			}
			return sum;
		}
		
		/**
		 * 递归分治求最大字段和问题
		 * 求一个序列的最大字段和可以递归分为左右两个字段分析,
		 * 分别求左右字段的最大字段和,以及从中间开始向两边伸展
		 * 的最大字段和,则该序列的最大字段和是它们三者之一。
		 * 时间复杂度为:O(n*log2(n))
		 * @param a 指定序列
		 * @param left 序列的左端索引
		 * @param right 序列的右端索引
		 * @return 序列的最大字段和
		 */
		public static int maxSum2(int[] a,int left, int right) {
			int sum = 0;
			if (left == right)//只有一个元素
				sum = a[left] > 0 ? a[left] : 0;
			else {
				int center = (left + right) / 2;
				//递归求左右字段的最大字段和
				int leftsum = maxSum2(a,left, center);
				int rightsum = maxSum2(a,center + 1, right);
				int s1 = 0;//从中间向左边伸展的最大字段和
				int lefts = 0;
				for (int i = center; i >= left; i--) {
					lefts += a[i];
					if (lefts > s1)
						s1 = lefts;
				}
				int s2 = 0;//从中间向右边伸展的最大字段和
				int rights = 0;
				for (int i = center + 1; i <= right; i++) {
					rights += a[i];
					if (rights > s2)
						s2 = rights;
				}
				sum = s1 + s2;
				if (sum < leftsum)
					sum = leftsum;
				if (sum < rightsum)
					sum = rightsum;
			}
			return sum;
		}
		
		/**
		 * 动态规划算法求解最大字段和问题:
		 * 假设(A[i],...,A[n-1])序列的最大字段和为all[i],
		 * (A[i],...,A[n-1])序列中包含A[i]的最大字段和为start[i],
		 * 则(A[i-1],A[i],...,A[n-1])序列的最大字段和为:
		 * max{A[i-1],A[i-1]+start[i],All[i]}.
		 * 性能:时间复杂度为O(n),辅助空间为2n
		 * 时间复杂度为:O(n)
		 * @param a 指定序列
		 * @return 最大字段和
		 */
		public  int maxSum3(int[] a) {
			int len=a.length;
			int[] start=new int[len];
			int[] all=new int[len];
			start[len-1]=a[len-1];
			all[len-1]=a[len-1];
			for(int i=len-2;i>=0;i--){
				start[i]=Math.max(a[i], a[i]+start[i+1]);
				all[i]=Math.max(start[i], all[i+1]);
			}
			return all[0];
		}
		
		/**
		 * 动态规划算法求解最大字段和问题:
		 * 假设(A[i],...,A[n-1])序列的最大字段和为all[i](存在nAll)
		 * (A[i],...,A[n-1])序列中包含A[i]的最大字段和为start[i](存在nStart)
		 * 则(A[i-1],A[i],...,A[n-1])序列的最大字段和为:
		 * max{A[i-1],A[i-1]+nStart,nAll}.
		 * 性能:时间复杂度为O(n),辅助空间为2(即O(1))
		 * 时间复杂度为:O(n)
		 * @param a 指定序列
		 * @return 最大字段和
		 */
		public  int maxSum4(int[] a) {
			int len=a.length;
			int nStart=a[len-1];
			int nAll=a[len-1];
			for(int i=len-2;i>=0;i--){
				nStart=Math.max(a[i], a[i]+nStart);
				nAll=Math.max(nStart, nAll);
			}
			return nAll;
		}
	
		/**
		 * 高效的动态规划求解最大字段和问题
		 * 时间复杂度为:O(n),辅助空间为2
		 * @param a 指定序列
		 * @return 最大字段和
		 */
		public  int maxSum5(int[] a) {
			int n = a.length;
			int sum = 0;//最大字段和
			int b = 0;//当前最大字段和
			for (int i = 0; i <n; i++) {
				if (b > 0)
					b += a[i];
				else
					b = a[i];
				if (b > sum)
					sum = b;
			}
			return sum;
		}
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值