社团活动每日一题:第十天 最大子序和

前言:这是我们大学社团给我们大一新生布置的每日一题任务,因为本人编程理解有限,参考价值较低。

题目链接https://leetcode-cn.com/problems/maximum-subarray/icon-default.png?t=L9C2https://leetcode-cn.com/problems/maximum-subarray/

         求最大连续子数组和的问题,比较经典的一个问题。我在尝试用题目本意去解题的过程中,很神奇的AC了,短时间解释不好,那我来讲个解决这个问题的大体思路吧,这个方法在算法竞赛中很常用,我建议如下分步理解:

第一步:暴力

很明显嘛,我去枚举一下所有连续子序列(先说一下这个会超时)不就好了?

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int L = nums.size(),ans=nums[0];
        for(int i=0;i<L;i++){
            for(int j=i;j<L;j++){
                int t=0;
                for(int k=i;k<=j;k++){
                    t+=nums[k];
                }
                ans = max(ans,t);
            }
        }
        return ans;
    }
};

第二步:用累加和法优化

        既然会超时,那我们优化一下。先这么想:我们求一下数组每一项的累加和,设它为数组sum[]  ,我们所要求的区间的累加和就是sum[j]-sum[i-1]了不是吗awa,代码如下(还是超时):

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int L = nums.size(),ans=nums[0];
        for(int i=1;i<L;i++){
            nums[i] += nums[i-1];
            ans = max(ans,nums[i]);
        }
        for(int i=1;i<L;i++){
            for(int j=i;j<L;j++){
                ans = max(ans,nums[j]-nums[i-1]);
            }
        }
        return ans;
    }
};

第三步:用玄学优化

       虽然我们已经避开了O(n^3)的暴力,但是O(n^2)的累加和方法也会超时,那么通用的方法就到此结束了,接下来开始的是玄学(bushi)做题时间awa

        当我们在遍历数组的时候,用一个临时变量t去存储从前到此元素的最优解,那么这个最优解应该怎么去找呢?先看几种情况下我们应有的思路:

        ①数列中没有负数

        这个情况很容易理解,我们到每一个元素的最优解都是前面所有数值包括这个数字的累加和

        ②数列全是负数

        这个情况就要让我们考虑到ans的初始值可以是nums[0]或-identfy,我们在求最优解时遇到前面所有项累加和的时候,若这个累加和小于0,就要重置为0,并且不能让ans与它比较。

        所以我们得到了如下的AC代码:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int L = nums.size(),ans=nums[0],t=0;
        for(int i=0;i<L;i++){
            t = max(0,t+nums[i]);
            ans = max(ans,nums[i]<0?nums[i]:t);
        }
        return ans;
    }
};

为什么看起来比之前两个解法简单呢?我也解释不清~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值