题解 | #连续子数组的最大和#

连续子数组的最大和

http://www.nowcoder.com/practice/459bd355da1549fa8a49e350bf3df484

题目陈述

题目大意:给定一个有正数有负数的数组,求解连续的一段的元素的和的最大值

算法1:暴力做法

算法思路

  • 枚举左右端点,然后计算这个区间的总和now,跟ans比较,如果比ans大,则更新ans,最后循环结束返回ans

  • 时间复杂度,空间复杂度

    代码实现

    class Solution
    {
    public:
      int FindGreatestSumOfSubArray(vector<int> array)
      {
          int ans = INT_MIN;
          int len = array.size();
          for (int i = 0; i < len; i++)//枚举左端点
          {
              for (int j = i; j < len; j++)//枚举右端
              {
                  int now = 0;
                  for (int k = i; k <= j; k++)//计算区间和
                  {
                      now += array[k];
                  }
                  ans = max(now, ans);//更新ans
              }
          }
          return ans;
      }
    };

    算法2:前缀和优化

    算法思路

  • 我们发现上面的过程中,会重复计算很多的子区间的总和,所以我们用前缀和优化,

  • 第一个数到第j个数的和,减去第一个数到第i-1个数的和,即得到第i个数到第j个数的和,即

  • 时间复杂度,空间复杂度(因为定义了一个sum数组)

    代码实现

    class Solution{
    public:
      int FindGreatestSumOfSubArray(vector<int> array)
      {
    
          int ans=INT_MIN;
          int len = array.size();
          vector<int> sum(len+1,0);
          //sum[0]设为空集,
          //sum[i+1]设为array[0,i]的和,其中i=0~len-1
          //约定array[-1]==0为空集
          for(int i=0;i<len;i++){
              sum[i+1]=sum[i]+array[i];//计算前缀和
          }
    
          for (int i = 0; i < len; i++)//约定array[-1]==0为空集
          {
              for (int j = i+1; j <= len; j++)
              {
                  ans=max(ans,sum[j]-sum[i]);//计算[i-1,j-1]的和
              }
          }
          return ans;
      };
    };

    算法3:动态规划

    算法思路

  • 设dp[n]为以第n个数为结尾,得到的子数组的和的最大值

  • 因为以第n个数为结尾所以array[n]是必然被选择的

  • 基于dp[n-1]的值,如果dp[n-1]>0,我们加上这个正数,我们的值是不是必然会增大

  • 如果dp[n-1]<0,那么我们加上负数,我们的值就会减小,这个时候我们不如不要前面的结果,只要当前这个数,结果反而更优

  • 于是我们就得到了状态转移方程dp[n]=array[n]+(dp[n-1]>0?dp[n-1]:0),实时跟ans比较,更新最大值即可

  • 时间复杂度,空间复杂度(定义了一个dp数组)

    优化算法(空间复杂度)

  • 我们可以发现当前状态只跟上一个状态有关,所以我们可以只用一个int来代替dp数组,即num

  • 如果num<0,那么这个时候就num=array[i]

  • 如果num>0,那么就num=num+array[i]

  • 然后实时跟ans比较,更新最大值即可

  • 时间复杂度,空间复杂度

    动画演示

    图片说明

    代码实现

    C++

    class Solution
    {
    public:
      int FindGreatestSumOfSubArray(vector<int> array)
      {
          int now, ans;
          now = 0, ans = INT_MIN;
          for (int i = 0; i < array.size(); i++)
          {
              if (now < 0)//now<0,则舍去前面的
                  now = array[i];
              else
              {
                  now += array[i];//比0大则直接加上去
              }
              ans = max(now, ans);//更新ans
          }
          return ans;
      }
    };

    python

    class Solution:
      def FindGreatestSumOfSubArray(self, array):
          now=0
          ans=-1000000000
          for i in array:#此处i即代表array里面的第i个元素的值
              if now<0 :
                  now=i#now<0,则舍去前面的
              else :
                  now+=i
              ans=max(ans,now)#更新ans
          return ans 
全部评论
1
点赞
送花
回复
分享
发布于 2022-01-20 22:58
前缀和的方式会超时
点赞
送花
回复
分享
发布于 2023-08-18 13:48 陕西
蔚来
校招火热招聘中
官网直投

相关推荐

28 10 评论
分享
正在热议
# 牛客帮帮团来啦!有问必答 #
1153099次浏览 17157人参与
# 通信和硬件还有转码的必要吗 #
11244次浏览 101人参与
# 不去互联网可以去金融科技 #
20787次浏览 259人参与
# 和牛牛一起刷题打卡 #
19108次浏览 1635人参与
# 实习与准备秋招该如何平衡 #
203529次浏览 3628人参与
# 大厂无回复,继续等待还是奔赴小厂 #
5019次浏览 33人参与
# OPPO开奖 #
19340次浏览 268人参与
# 通信硬件薪资爆料 #
266087次浏览 2484人参与
# 国企是理工四大天坑的最好选择吗 #
2236次浏览 34人参与
# 互联网公司评价 #
97763次浏览 1280人参与
# 简历无回复,你会继续海投还是优化再投? #
25041次浏览 354人参与
# 0offer是寒冬太冷还是我太菜 #
454983次浏览 5125人参与
# 国企和大厂硬件兄弟怎么选? #
53928次浏览 1013人参与
# 参加过提前批的机械人,你们还参加秋招么 #
14649次浏览 349人参与
# 硬件人的简历怎么写 #
82299次浏览 852人参与
# 面试被问第一学历差时该怎么回答 #
19415次浏览 213人参与
# 你见过最离谱的招聘要求是什么? #
28564次浏览 248人参与
# 学历对求职的影响 #
161286次浏览 1804人参与
# 你收到了团子的OC了吗 #
538895次浏览 6389人参与
# 你已经投递多少份简历了 #
344350次浏览 4963人参与
# 实习生应该准时下班吗 #
97035次浏览 722人参与
# 听劝,我这个简历该怎么改? #
63530次浏览 622人参与
牛客网
牛客企业服务