浙大数据结构习题笔记:最大子列和问题

前言
本学习学校开了数据结构这么课,但本人感觉一学期没怎么听,基本的一些东西也搞不出来那种,觉得这个假期有必要在考试之前重新预习一遍……
找了找觉得浙大陈越老师讲的网课不错,于是就准备重新跟一遍数据结构的网课。

01-复杂度1 最大子列和问题

#include <stdio.h>
#include <string.h>

int MaxSum1(int A[],int N)
{
    int oneSum,maxSum = 0;
    int i,j,k;
    for(i=0;i<N;i++){   //i为左端
        for(j=i;j<N;j++){   //j为右端
            oneSum = 0;
            for(k=i;k<=j;k++){
                oneSum += A[k];
            }
            if(maxSum < oneSum){
                maxSum = oneSum;
            }
        }
    }
    return maxSum;
}

int MaxSum2(int A[],int N)
{
    int oneSum,maxSum = 0;
    int i,j;
    for(i=0;i<N;i++){   //i为左端
        oneSum = 0; 
        for(j=i;j<N;j++){   //j为右端
            oneSum += A[j];     //相同i,不同j,累计加比较
            if(oneSum > maxSum)
                maxSum = oneSum;        
        }
    }
    return maxSum;
}

int MaxSum4(int A[],int N)  //在线处理
{
    int oneSum=0;
    int maxSum=0;
    int i;
    for(i=0;i<N;i++){
        oneSum += A[i]; //向右侧累加
        if(oneSum > maxSum){
            maxSum = oneSum;   
        }else if(oneSum <0){
            oneSum = 0; //发现为负,必不可能,归零
        }
    }
    return maxSum;
}

int maxOfThree(int a,int b,int c)
//三者最大
{
    return (a>b)?((a>c)?a:c):((b>c)?b:c);
}

int divide(int a[],int left,int right)
{
    if(left == right){  //只有一个数字时结束递归
        if(a[left]>0)
            return a[left];
        return 0;
    }
    int center = (left+right)/2;
    int maxLeft = divide(a,left,center);
    int maxRight = divide(a,center+1,right);

    int i=0;
    int maxLeftBorder = 0;
    int leftBorder = 0;
    for(i=center;i>=left;i--){  //从边界向左
        leftBorder += a[i];
        if(maxLeftBorder<leftBorder)
            maxLeftBorder = leftBorder;
    }

    int maxRightBorder = 0;
    int rightBorder = 0;
    for(i=center+1;i<=right;i++){   //边界向右
        rightBorder += a[i];
        if(maxRightBorder<rightBorder)
            maxRightBorder = rightBorder;
    }

    return maxOfThree(maxLeft,maxRight,maxRightBorder+maxLeftBorder);
}

int MaxSum3(int A[],int n)
{
    return divide(A,0,n-1);
}

int main()
{
    int list[6] = {-2,11,-4,13,-5,-2};
    int max1 = MaxSum1(list,6);
    printf("problem 1 = %d\n",max1);
    int max2 = MaxSum2(list,6);
    printf("problem 2 = %d\n",max2);
    int max3 = MaxSum3(list,6);
    printf("problem 3 = %d\n",max3);
    int max4 = MaxSum4(list,6);
    printf("problem 4 = %d\n",max4);
    return 0;    
}

#problem 1 = 20
#problem 2 = 20
#problem 3 = 20
#problem 4 = 20

四种方法在慕课中都有讲到

此外,PTA中的升级版版本:

Maximum Subsequence Sum

输入:

10
-10 1 2 3 4 -5 -23 3 7 -21

输出:

10 1 4
#include <stdio.h>
#define maxn 10005
#define INF 0x3f3f3f3f
int a[maxn];
int n;
void f() {
    int lsLeft=0, right=0, left=0;//lsLeft为临时左下标,left为最大子序列最左边下标,right为最右边下标
    int ThisSum=0, MaxSum=-INF;//首先ThisSum代表临时子列和,MaxSum为最大子列和
    for (int i = 0; i < n; i++) {
        ThisSum += a[i];
        if (ThisSum < 0) {
            ThisSum = 0;
            lsLeft = i+1;//更新临时下标
        }
        else if (ThisSum > MaxSum) {
            MaxSum = ThisSum;
            left = lsLeft;//更新左下标
            right = i;//右下标
        }
    }
    if (MaxSum < 0) {
        printf("0 %d %d", a[0], a[n-1]);
    }
    else {
        printf("%d %d %d", MaxSum, a[left], a[right]);
    }
}
int main() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d", &a[i]);
    }
    f();
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值