问题描述
给定一个数组,有正有负,乱序,要求找两个不重叠的子数组,使得这两个子数组元素的和最大。(一个子数组内元素下标是连续的。)
输入:[-3,1,2,3,-1,2,8,0,-1,-6,9,2]
输出:26
C++代码
正向和逆向两次动态规划,构建两个dp数组,保存从左(右)到当前元素的子数组和。
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int getMaxTwoArraySum(vector<int>& vec){
int length = vec.size();
vector<int> dp(vec.size(), 0);
vector<int> dp_inverse(vec.size(), 0);
// 构造dp数组
dp[0] = vec[0];
dp_inverse[length - 1] = vec[length - 1];
for(int i = 1; i < length; i++){
if(dp[i -1] > 0) {
dp[i] = dp[i - 1] + vec[i];
}else{
dp[i] = vec[i];
}
if(dp_inverse[length - i] > 0){
dp_inverse[length - i - 1] = dp_inverse[length - i] + vec[length - i - 1];
}else{
dp_inverse[length - i - 1] = vec[length - i -1];
}
}
// 打印正向dp数组
for(int i = 0; i < length; i++){
cout << dp[i] << " ";
}
cout << endl;
// 打印逆向dp数组
for(int i = 0; i < length; i++){
cout << dp_inverse[i] << " ";
}
cout << endl;
// 将dp数组的值替换为从左(右)开始到当前位置最大的子数组长度
for(int i = 1; i < length; i++){
dp[i] = max(dp[i], dp[i-1]);
dp_inverse[length - i - 1] = max(dp_inverse[length - i - 1], dp_inverse[length - i]);
}
int max_sum = 0;
for(int i = 0; i < length - 1; i++){
int sum = dp[i] + dp_inverse[i+1];
max_sum = max(sum, max_sum);
}
return max_sum;
}
int main(){
vector<int> vec = {-3,1,2,3,-1,2,8,0,-1,-6,9,2};
cout << getMaxTwoArraySum(vec) << endl;
return 0;
}
代码分析
时间复杂度:O(n),只有一层循环;
空间复杂度:O(n),创建了两个 dp 数组。