算法第3章上机实践报告

一、实践题目

 

7-2 最大子段和 (40 分)

给定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

二、问题描述

 

给出一段序列,求其中一段连续序列的最大值。

 

三、算法描述

 

递推方程式:dp[i] += dp[i-1];

易知当一段序列和为负数的时候必定不会是最大值。

所以当循环 dp[i] += dp[i-1] 时,dp[i] < 0 就把 dp[i] 置为 0。

在循环过程中,用一个 ans = ans>dp[i] ? ans:dp[i]; 记录最大值即可。

为了减少时间、空间复杂度,根据本题思路,在输入时即可直接记录。

故只开了 num 用于输入,dp = 0 用于记录当前连续的和,ans = 0 记录最大值。 

 

具体代码:

#include <iostream>
using namespace std;
int n;
int num, dp = 0, ans = 0;
int main(){
    scanf("%d", &n);
    while(n--){
        scanf("%d", &num);
        dp += num; 
        if(dp<0){
            dp = 0;
        }
        else{
            ans = ans>dp ? ans:dp;
        }
    }
    printf("%d", ans);
    return 0;
}

 

四、算法时间及空间复杂度分析(要有分析过程)

 

时间复杂度:1 + n * ( 1 + 1 + 1 * ( 1 + 1 ) ) + 1 = 1 + n + 1 = O(N)

输入n : 1

{

// n 轮操作

输入num : 1

dp累加求和 : 1

判断dp是否小于0 : 1

{

小于0

{

dp置为0 : 1

}

大于等于0

{

判断ans是否大于dp : 1

ans赋值 : 1

}

}

}

输出ans : 1

 

空间复杂度:1 + 1 + 1 + 1 = O(1)

n : 1

num : 1

dp = 0 : 1

ans = 0 : 1

 

五、心得体会(对本次实践收获及疑惑进行总结)

 

跟队友交流了一下,发现队友 7 - 1 的思路跟我不一样,我是自顶向下把最后一行的所有格子的最大值求出来,再循环求最大。队友的是自底向上直接求出最大值。

两个都不会 7 - 3 编辑距离,都研究了一会,上网学习了一回。收获就是思想碰撞,单题多解。

posted @ 2018-11-05 12:02  请你吃糖呀  阅读(183)  评论(0编辑  收藏  举报