51nod-1049 最大子段和(分治和动态规划)

                                        1049 最大子段和

基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题

 收藏

 关注

N个整数组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的连续子段和的最大值。当所给的整数均为负数时和为0。

例如:-2,11,-4,13,-5,-2,和最大的子段为:11,-4,13。和为20。

Input

第1行:整数序列的长度N(2 <= N <= 50000)
第2 - N + 1行:N个整数(-10^9 <= A[i] <= 10^9)

Output

输出最大子段和

Input示例

6
-2
11
-4
13
-5
-2

Output示例

20

思路:

1.可以使用动态规划也可以使用分治 

2.动态规划见传送门(我我我是传送门)

3.下面来分析一下使用分治思想来解决

4.把数组分为左右两段,可以猜想最大子序列不在左边这一段就是在右边这一段,当然还有跨越中间边界的情况

5.跨越中间边界的情况可以在mid点往左边扫找出最大的和,然后可以在mid点往右边扫找出最大的和,然后跨越中间边界最大的和就是他们的相加和

6.左边和右边的情况可以使用递归

贴代码:

package a51nodWeb.acm;

import java.util.Scanner;

public class M1049 {
	public static long maxSub(long[] nums, int left, int right) {
		if(left==right) {
			if(nums[left]<0) {
				return 0;
			}else {
				return nums[left];
			}
		}
		int mid = (left+right)/2;
		long maxL = maxSub(nums, left, mid);
		long maxR = maxSub(nums, mid+1, right);
		long maxLeft = 0;
		long maxRight = 0;
		long thisSumLeft=0;
		long thisSumRight = 0;
		for (int i = mid; i>=left; i--) {
			thisSumLeft+=nums[i];
			if(thisSumLeft>maxLeft) {
				maxLeft = thisSumLeft;
			}
		}
		for (int i = mid+1; i < nums.length; i++) {
			thisSumRight+=nums[i];
			if(thisSumRight>maxRight) {
				maxRight = thisSumRight;
			}
		}
		return getMax(maxL, maxR, maxLeft+maxRight);
	}

	public static long getMax(long a, long b, long c) {
		if (a < b) {
			a = b;
		}
		if (a < c) {
			a = c;
		}
		return a;
	}

	public static void main(String[] args) {
		Scanner in = new Scanner(System.in);
		int n = in.nextInt();
		long[] nums = new long[n];
		for (int i = 0; i < nums.length; i++) {
			nums[i] = in.nextInt();
		}
		System.out.println(maxSub(nums, 0, nums.length-1));
	}
}

但是......Java使用O(nlogn)其他语言应该可以过好像有两组数字还是超时的,所以还是使用一手动态规划:

坑点:别忘了相加超出int的情况

package pta;

import java.util.Scanner;

public class PTA7_1最大子列和问题 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner in = new Scanner(System.in);
		int K = in.nextInt();
		int[] nums = new int[K];
		for (int i = 0; i < nums.length; i++) {
			nums[i] = in.nextInt();
		}
		long thisSum = 0;
		long maxSum = 0;
		for (int i = 0; i < nums.length; i++) {
			thisSum+=nums[i];
			if(thisSum>maxSum) {
				maxSum = thisSum;
			}
			if(thisSum<0) {
				thisSum = 0;
			}
		}
		System.out.println(maxSum);
	}

}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值