求解最大连续子序列和的几种方法(C语言版)

求解最大连续子序列和,即以下问题

给定一个整数数组arr及其长度arrSize,试找到一个具有最大和的连续子数组(子数组至少包含一个元素),返回其最大和。
示例:int maxSubSum_BF(int *arr, int arrSize)
①输入[4,-3,5,-2],输出6
②输入[-1,2,-6,3],输出3
③输入[4,-3,5,-2,-1,2,6,-2],输出11

下面我们将采取不同方法,从不同角度解决这个问题

穷举法

首先自然是暴力的穷举法了。

int maxSubArray(int* nums, int numsSize){
    int sum = 0;
    int max = nums[0];
    for(int i=0;i<numsSize;i++){
            for(int j=i;j<numsSize;j++,sum=0){    
                    for(int k=i;k<=j;k++)
                            sum += nums[k];
                    max = max>sum?max:sum; 
                }
        }
    return max;
}//时间复杂度O(n^3)

测试一下,没有问题。通过用例
提交一下,没有……?超时了。超出时间限制
难道就不能用穷举法了吗?我不甘心,再优化一下。

int maxSubArray(int* nums, int numsSize){
    int sum = 0;
    int max = nums[0];
    for(int i=0;i<numsSize;i++,sum=0){
            for(int j=i;j<numsSize;j++){    
                   sum += nums[j];
                    max = max>sum?max:sum; 
                }
        }
    return max;
}//时间复杂度O(n^2)

依然是穷举,但减少了重复计算,时间复杂度从n3让降低到了n2,我们拭目以待。
在这里插入图片描述
仍有一个用例未通过……失败。看来穷举法这条路是走不通了,让我们试试其他方法。

贪心法

只要连续子序列的和为正,那么它就有可能连接上后面的数,成为最大子序列和。但如果一个连续子序列的和为负,那它就没有价值,可以彻底放弃。

于是,我们用贪心法:

int maxSubArray(int *arr, int arrSize) {
    int count = 0, maxSum = INT32_MIN;
    for (int i = 0; i < arrSize; i++) {
        count += arr[i];
        if (count > maxSum) maxSum = count;
        if (count <= 0) count = 0; 
        }
    return maxSum;
}//maxSubSum_Greedy

动态规划法

int maxSubArray(int *arr, int arrSize) {
    int *dp, maxSum = arr[0];
    dp = malloc(sizeof(int)*arrSize); //创建表
    dp[0] = arr[0]; //初始化表
    for (int i = 1; i < arrSize; i++) {//按状态递推关系更新表   
        dp[i] = dp[i-1]+arr[i]> arr[i]?dp[i-1]+arr[i]: arr[i];
        if (dp[i] > maxSum) maxSum = dp[i];
        }
    free(dp);
    return maxSum;
}//maxSubSum_D

不过嘛,在这道题上,动态规划法化简一下,就会发现又变成了贪心法的样子……

具体到这道题,我个人比较喜欢贪心法。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值