注:七月在线听课笔记
53:最大子数组和
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4]
,
the contiguous subarray [4,-1,2,1]
has the largest sum = 6
.
给定数组a[1,2,3,...,n],求最大子数组和,即找出1<= i <= j <= n,使得a[i]+a[i+1]+......+a[j]最大。
三种解法:
暴力枚举法 时间复杂度O(n3)(三次方)
优化枚举 时间复杂度O(n2)(平方)
贪心法 时间复杂度O(n)
一:暴力枚举(三重循环)
伪代码如图所示:
代码一:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int ans = -2147483647;
for (int st = 0;st < n; ++st)
for(int ed = st+1;ed <= n; ++ed){
int sum =0;
for(int i = st;i< ed;++i)
sum += nums[i];
if (sum > ans)
ans = sum;
}
return ans;
}
};
结果:超时
二:优化枚举(二重循环)
伪代码如图所示:
代码二:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int ans = -2147483647;
for (int i = 0;i < n; ++i){
int sum = 0;
for(int j = i+1;j <= n; ++j){
sum += nums[j-1];
if (sum > ans)
ans = sum;
}
}
return ans;
}
};
结果:超时
三:贪心法(一重循环)
伪代码如图所示:
推理过程:
代码三:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int ans = -2147483647;
int sj=0;
int minSi=0;
int si=0;
for (int j = 0;j < n; ++j){
sj += nums[j];
if (si <minSi)
minSi = si;
if (sj-minSi>ans){
ans = sj-minSi;
}
si += nums[j];
}
return ans;
}
};
变换简化:
minSi>0是没有意义的,即minSi的最大值是0
则令sum = si-minSi
另外,sj = si+nums[j]
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int ans = -2147483647;
int sum = 0;
for (int j = 0;j < n; ++j){
if (sum <0)
sum= 0;
if (sum+nums[j]>ans){
ans = sum+nums[j];
}
sum += nums[j];
}
return ans;
}
};
贪心法形式:
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n = nums.size();
int ans = -2147483647;
int sum = 0;
for (int j = 0;j < n; ++j){
sum += nums[j];
if (sum>ans)
ans = sum;
if (sum <0)
sum= 0;
}
return ans;
}
};
结果:通过