题目描述:
给定一个整数数组,找到一个具有最大和的子数组,返回其最大和。
注意:子数组最少包含一个元素
例如:
给出数组[−2,2,−3,4,−1,2,1,−5,3],符合要求的子数组为[4,−1,2,1],其最大和为6
思路1:穷举法
三层循环,穷举出所有子数组,分别求子数组的和,找到其中和最大的一个。
时间复杂度:O(n3)
class Solution
{
public:
int maxSubArray(vector<int> nums)
{
int length = nums.size();
int max = INT_MIN;
for(int i = 0; i < length; i++)
{
for(int j = i; j < length; j++)
{
int sum = 0;
for(int k = i; k <= j; k++)
{
sum = sum +nums[k];
}
if(sum > max)
{
max = sum;
}
}
}
return max;
}
};
思路2:穷举法
两层层循环,穷举出所有子数组,分别求子数组的和,找到其中和最大的一个。
时间复杂度:O(n2)
class Solution
{
public:
int maxSubArray(vector<int> nums)
{
int length = nums.size();
int max = INT_MIN;
for(int i = 0; i < length; i++)
{
int sum = 0;
for(int j = i; j < length; j++)
{
sum = sum +nums[j];
if(sum > max)
{
max = sum;
}
}
}
return max;
}
};
思路3:贪心法
如果是负数,则抛弃前面所有的数字之和,重新开始计算。
时间复杂度:O(n)
class Solution
{
public:
int maxSubArray(vector<int> nums)
{
int max = nums[0];
int sum = max;
for(int i = 1; i < nums.size(); i++)
{
if (sum < 0)
{
sum = 0;
}
sum += nums[i];
if (sum > max)
max = sum;
}
return max;
}
};
思路4:动态规划
对于第i个数,有两种选择:一种是把它加入在子数组里,另一种是不加入子数组(子数组到此结束) 。加不加入子数组,要比较它加入前后子数组的总和是变大了还是变小了,如果变大则加入,变小则不加入 。所以,我们需要记录以i-1结尾的子数组的总和,最后的结果在这些总和中取最大的那个 。
实现时用两个变量,一个保存f[i-1],一个保存目前为止最大的f[i]
f[i] = max(f[i-1]+a[i],f[i-1]);
max({f[i]})
复杂度:时间O(n),空间O(1)
参考博客:Leetcode 动态规划 Maximum Subarray
class Solution
{
public:
int maxSubArray(vector<int> &nums)
{
int max_fi = INT_MIN;
int fi = 0;
for(size_t i = 0; i < nums.size(); i++)
{
fi = max(fi + nums[i], nums[i]);
max_fi = max(max_fi, fi);
}
return max_fi;
}
};