牛客网刷题|连续子数组的最大和

题目来源:牛客网

编程连接

题目描述

HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。你会不会被他忽悠住?(子向量的长度至少是1)

题目解析:

题目很经典,在数据结构书里的例子,还能说什么呢?
很多种解法,先来一个暴力解法,算法复杂度0(n^2)

代码:
遍历所有的连续子数组,把最大的保存起来输出即可。
每次有个新起点时,需要把和置为0.

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        int ThisSum,i,j = 0;
        int MaxSum =  0x80000000;
        for(int i = 0;i<array.size();i++)
        {
            ThisSum = 0;
            for(int j = i;j<array.size();j++)
            {
                ThisSum  += array[j];
                if(ThisSum > MaxSum) 
                {
                    MaxSum = ThisSum;
                }
            }
        }      
        return MaxSum;           
    }
};

运用动态规划的思想,一直记录当前值和下一个值做比较

/*
算法时间复杂度O(n)
用total记录累计值,maxSum记录和最大
基于思想:对于一个数A,若是A的左边累计数非负,那么加上A能使得值不小于A,认为累计值对
          整体和是有贡献的。如果前几项累计值负数,则认为有害于总和,total记录当前值。
此时 若和大于maxSum 则用maxSum记录下来
*/
public class Solution {
    public int FindGreatestSumOfSubArray(int[] array) {
        if(array.length==0)
            return 0;
        else{
            int total=array[0],maxSum=array[0];
            for(int i=1;i<array.length;i++){
                if(total>=0)
                    total+=array[i];
                else
                    total=array[i];
                if(total>maxSum)
                    maxSum=total;
            }
            return maxSum;
        }

    }
}

优化后的代码:

链接:https://www.nowcoder.com/questionTerminal/459bd355da1549fa8a49e350bf3df484
来源:牛客网

int FindGreatestSumOfSubArray(vector<int> array) {
        if(array.empty()) return 0;
        int sum = array[0], tempsum = array[0]; //注意初始值 不能设为0 防止只有负数
        for(int i = 1; i < array.size(); i++) //从1开始 因为0的情况在初始化时完成了
        {
            tempsum = (tempsum < 0) ? array[i] : tempsum + array[i];
            sum = (tempsum > sum) ? tempsum : sum;
        }
        return sum;
    }

另外一种写法:

链接:https://www.nowcoder.com/questionTerminal/459bd355da1549fa8a49e350bf3df484
来源:牛客网

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> a) {
      if(!a.size()) return 0;
        int mx = 0x80000000;
        for(int i = 0, s = 0; i < int(a.size()); ++i){
            s = max(s + a[i], a[i]);  //因为加上a[i]还小于a[i]的话就说明前面的s小于0
            mx = max(mx, s);
        }
        return mx;
    }
};

一种搞怪的思路;
先把遍历数组,依次求和并保存。
子数组和就是结束位置的和减去起始位置的和,
记录最大的子数组和。
代码如下:

class Solution {
public:
    int FindGreatestSumOfSubArray(vector<int> array) {
        vector<int>sum(array);
        int ret = -0x3f3f3f3f;
        for(int i = 1;i<array.size();sum[i] = sum[i-1] + array[i],i++);
        for(int len = 1;len <= array.size();len++)
        {
            for(int i = 0;i+len-1<array.size();i++)
            {                
                ret = max(ret,sum[len+i-1] - (i?sum[i-1]:0));
            }
        }
        return ret;  
    }
};

猜你喜欢

转载自blog.csdn.net/legalhighhigh/article/details/80213413
今日推荐