版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_28584889/article/details/83754712
先上题目:
方法一:O(N^3)暴力解法(会报超时)
//方法一:O(N^3)暴力解法(会报超时)
/*
O(N^3)的暴力解法比较容易想到,就是利用三层循环遍历计算每个可能的子序列,求其和并进行比较
但是因为时间复杂度太大,在LeetCode会报超时。
*/
int maxSubArray(vector<int>& nums) {
int maxSum = nums[0];
int tmpSum;
for (int i = 0; i < nums.size(); i++) //子序列的左边起始点
{
for (int j = i; j < nums.size(); j++) //子序列的右边结束点
{
tmpSum = 0;
for (int k = i; k <= j; k++) //计算每个子序列的和
{
tmpSum += nums[j];
}
if(tmpSum > maxSum)
maxSum = tmpSum; //如有子序列的和更大的,则更换当前的最大子序列和
}
}
return maxSum;
}
方法二:O(N^2)改进暴力解法
//方法二:O(N^2)改进暴力解法
/*
仔细观察上面的暴力解法,我们发现在第三层循环计算子序列的和的时候,每次都要重复计算之前计算过的
子序列和,所以所可以改进;其实就是可以把第三次循环扔掉,计算子序列和的时候每加一个元素就比较一次
因为时间复杂度有所下降,所以在LeetCode可以通过。
*/
int maxSubArray(vector<int>& nums) {
int maxSum = nums[0];
int tmpSum;
for (int i = 0; i < nums.size(); i++)
{
tmpSum = 0;
for (int j = i; j < nums.size(); j++)
{
tmpSum += nums[j];
if(tmpSum > maxSum)
maxSum = tmpSum;
}
}
return maxSum;
}
方法三:O(N)扫描法(动态规划法)
//方法三:O(N)扫描法(动态规划法)
/*
该算法比较巧妙,只需一轮循环就可解决,线性复杂度。
具体思路就是:从第一个元素开始计算最大子序和,并且用tmpSum来记录当前的最大子序和,从头到尾遍历,
如果tmpSum为负,那么它就会拖低之后的子序和计算,所以应该重新定位当前的子序和temSum;如果tmpSum为
正,则加上当前的元素值。最后在每次的循环最后比较一下tmpSum和maxSum的值,如果tmpSum比maxSum大,则替换。
*/
int maxSubArray_second(vector<int>& nums) {
int maxSum = nums[0];
int tmpSum = nums[0];
for (int i = 1; i < nums.size(); i++)
{
if(tmpSum < 0) //当前数小于0 肯定会舍去(否则将会影响接下来的和),换为下一个数
tmpSum = nums[i];
else
tmpSum += nums[i]; //如果当前数不小于0,那么他会对接下来的和有积极影响
if(tmpSum > maxSum)
maxSum = tmpSum; //这里既实现了负数返回最大也实现了扫描法
//这里其实已经隐式的列举了所有可能,保留了所有可能的最大值
}
return maxSum;
}
最后,还有一种分治法的,时间复杂度为O(NlogN),比较复杂,懒得写了哈哈~