算法设计与分析第二章作业

算法设计与分析第二章作业

题目描述

给定n个整数(可能为负数)组成的序列a[1],a[2],a[3],…,a[n],求该序列如a[i]+a[i+1]+…+a[j]的子段和的最大值。当所给的整数均为负数时,定义子段和为0。(要求算法的时间复杂度为O(n)。)

输入格式:输入有两行:第一行是n值(1<=n<=10000);第二行是n个整数。
输出样式:输出最大子段和。

输入样例:
6
-2 11 -4 13 -5 -2

输出样例:
20

**思路:**若n=1(即序列中只有1个元素),若该元素大于0,则返回该元素;否则返回0(定义一个序列的最大连续子段和至少为0,若元素全为负数,定义其和为0);

  1. 该子序列完全落在左半部,即a[0…mid]中,采用递归求最大连续子段和maxLeftSum;
  2. 该子序列完全落在右半部,即a[mid+1…n-1]中,采用递归求最大连续子段和maxRightSum;
  3. 该子序列跨越a的中部而占据左右部分,以中间元素amid为界,向左边部分和右边部分扩张,以左边为例,定义leftBorderSum=0,maxLeftBorderSum=0
  4. 让leftBorderSum从中间让左边累加,如果遇到正数就把正数加上去,并把结果赋值给maxleftBorderSum (表现形式就是如果leftBorderSum > maxLeftBorderSum说明加了个正数);
  5. 右边同样的道理。最后 maxMidSum = maxleftBorderSum + maxRightBorderSum
  6. 比较出1,2,3,中所求的数那一个最大即为所求结果。

关键: 以数组中点为界,目标值只能在三处—要么在中点左边(不含中点),要么必须包含中点,要么右边(不含中点)。

伪代码:

int maxSubSum(int *a, int left, int right) {
	if (left == right) {
		return a[left] < 0 ? 0 : a[left];
	}
	    int centor = (left + right) / 2;
    int leftSum = maxSubSum(a, left, centor);
    int rightSum = maxSubSum(a, centor + 1, right);
    int s1 = 0;
    int lefts =0;
    for (int i = centor; i >= left; i--) { // 从中点向左找最大字段和
        lefts += a[i];
        if (lefts > s1) {
            s1 = lefts;
        }
    }
    int s2 = 0;
    int rights = 0;
    for (int i = centor + 1; i <= right; i++) {//从中点向右找最大字段和
        rights += a[i];
        if (rights > s1) {
            s1 = rights;
        }
    }
    int sum = s0 + s1; // 第三种情况的最大子段和
    sum = max(sum, leftSum); // 求解三种情况的最大值
    sum = max(sum, rightSum);
    return sum;
}
int maxSum(int *a, int n) {
	return sumSubSum(a, 1, n); // 可以根据数组a自行调整
}


时间复杂度O(logN)

空间复杂度O(logN)–来源递归调用栈产生的空间

心得体会

分治法概念上理解就是将整个问题分解成若干小问题后再分而治之。如果分解得到的子问题相对来说还是太大,则可反复使用分治策略将这些子问题分成更小的同类型子问题,直至产生方便求解的子问题,必要时逐步合并这些子问题的解,从而得到问题的解,类似一个递归过程。分治法是一种设计算法的思想,大大优化了算法的运行时间复杂度,优化了程序,如何熟练使用需要继续进行不断地练习才能感悟。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值