分而治之篇之最大子数组问题



问题描述

给定一个数组arr[1…n],对于任意一堆数组下标为l,r(l<=r)的非空子数组,其和记为S(l,r)= ∑ i = l r a r r [ i ] \sum_{i=l}^rarr[i] i=lrarr[i]
求出s(l,r)的最大值,记为Smax.


一、暴力枚举

1.问题分析

  • 数组arr[1…n],其所有的下标l,r(l<=r)组合分为以下两种情况

    • 当l=r时,一共n种组合
    • 当l<r时,一共C(n,2)种组合
  • 枚举n+C(n,2)种下标l,r组合,求出最大子数组之和

2.伪代码

这里是引用

3.代码实现

int sum(int *arr){
    int smax = INT16_MIN;
    
    for (int l = 0; l < 9;l++){
        for (int r = l; r < 9;r++){
            int s = 0;
            for (int i = l; i < r;i++){
                s = s + arr[i];
            }
            smax = max(smax, s);
        }
            
    }
    return smax;
}

二、优化枚举

1.优化分析

上述枚举中,含有多次的重复操作,例如:S(3,8)需要将下标为3到下标为8的值相加,S(3,9)需要将下标为3到下标为9的值相加,其中3到8已经相加过了,可以重复利用之前已经计算的数据,以达到优化的目的。

在这里插入图片描述

2.伪代码

这里是引用

3.代码实现

int sum(int *arr){
    int smax = INT16_MIN;
    
    for (int l = 0; l < 9;l++){
        int s = 0;
        for (int r = l; r < 9;r++){        
            s = s + arr[r];
            smax = max(smax, s);
        }       
    }
    return smax;
}

三、分治算法

1.算法流程

在这里插入图片描述

2.伪代码

在这里插入图片描述

在这里插入图片描述

3.代码实现

int CrossingSubArray(int* arr,int low,int mid ,int high){
    
    int smax_left = INT16_MIN,smax_right=INT16_MIN;
    int sum_left = 0,sum_right=0;
    for (int i = mid; i >= low; i--){
        sum_left = sum_left + arr[i];
        smax_left = max(sum_left, smax_left);
    }
    for (int i = mid + 1; i <= high;i++){
        sum_right = sum_right + arr[i];
        smax_right = max(sum_right, smax_right);
    }
    return smax_left + smax_right;
}
int MaxSubArray(int *arr ,int low,int high){

    if (low==high)
        return arr[low]; 
    int mid = (low + high) / 2;
    int s1=MaxSubArray(arr, low, mid);
    int s2=MaxSubArray(arr, mid + 1, high);
    int s3=CrossingSubArray(arr,low,mid,high);
    return max(max(s1, s2), s3);
}

四、总结

算法名称时间复杂度
暴力枚举O(n3)
优化枚举O(n2)
分而治之O(nlogn)
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值