53.最大子数组和及武大机试真题
53.最大子数组和
暴力解法1:枚举左右端点在对区间内的值求和
class Solution {
public:
int maxSubArray(vector<int>& nums) {
// 暴力解 O(n^3)=枚举左端点+枚举右端点+求左端点到右端点的和sum
// 但对左端点到右端点求和,这一步可以简化为O(1),从而整体复杂度达到O(n^2)
// 因为在确定了左端点的前提下,枚举右端点,sum每次加一个右端点元素即可
int maxSum = -10e6;
int start = 0, end = 0;
for (int left = 0; left < nums.size(); left++) {
int temp = 0;
for (int right = left; right < nums.size(); right++) {
temp += nums[right];
if (maxSum < temp) {
maxSum = temp;
start = left;
end = right;
}
}
}
return maxSum;
}
};
动态规划解法2:f[i]表示以i为结尾,0~i子数组的最大子数组和
f[i]状态转移方程:if(f[i-1]<0)f[i]=nums[i];else f[i]=f[i-1]+nums[i];
class Solution {
public:
int maxSubArray(vector<int>& nums) {
vector<int> f(nums.size());
f[0]=nums[0];
int max=nums[0];
for(int i=1;i<nums.size();i++){
if(f[i-1]<0)f[i]=nums[i];
else{
f[i]=f[i-1]+nums[i];
}
if(max<f[i])max=f[i];
}
return max;
}
};
武大真题要在求出最大子数组和的基础上,输出最大子数组的下标
思路:递归求解f[i]并将f[i]与maxSum进行比较 如果f[i]大于maxSum则更新leftIndex,rightIndex。此时的最大子数组的右端点rightIndex必然是i,左端点leftIndex是tempStart。
tempStart记录着当前以i为结尾的最大子数组和的左端点。
#include<iostream>
#include<vector>
using namespace std;
int main() {
vector<int> nums= {-10,-7,-8};
int maxSum=nums[0];
int leftIndex=0,rightIndex=0;
vector<int> f(nums.size(),0);//f[i]表示以i为结尾的子数组的最大子数组和。因为f[]必然包含题解
f[0]=nums[0];
int tempStart=0;
//
for(int i=1; i<nums.size(); i++) {
if(f[i-1]>=0) {
f[i]=f[i-1]+nums[i];
}
else {
f[i]=nums[i];
tempStart=i;
}
if(f[i]>maxSum){
rightIndex=i;
leftIndex=tempStart;
maxSum=f[i];
}
}
printf("最大子数组和为: %d。左端点: %d右端点: %d",maxSum,leftIndex+1,rightIndex+1);
return 0;
}

浙公网安备 33010602011771号