题目来源:牛客网
题目描述
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;
}
};