裸dp,T掉了
/*
* @lc app=leetcode id=123 lang=cpp
*
* [123] Best Time to Buy and Sell Stock III
*/
// @lc code=start
class Solution {
public:
int maxProfit(vector<int>& prices) {
int N = prices.size();
if(N <= 0) return 0;
vector<vector<int>> dp(2,vector<int>(N,0));
// 第一次
int minp = prices[0];
for(int i=0;i<N;i++){
dp[0][i] = prices[i] - minp;
minp = min(minp,prices[i]);
}
// 第二次
for(int i=0;i<N;i++){
minp = prices[i];
for(int j=i-1;j>=0;j--){
minp = min(minp,prices[j]);
dp[1][i] = max(dp[1][i],prices[i]-minp+dp[0][j]);
}
}
int ans = 0;
for(int i=0;i<N;i++) ans = max(ans,dp[1][i]);
return ans;
}
};
// @lc code=end
数据10^5,所以O(N ^2)肯定过不了。
发现第二次买卖双重循环太耗时,
仔细分析发现,两次买卖绝对不会重合(边界点相交不算)
所以,可以枚举中间点,
然后dpL[i]表示[0:i]买卖一次最大收益,dpR[i]表示[i:N-1]买卖一次最大收益,O(N)就解决了。
/*
* @lc app=leetcode id=123 lang=cpp
*
* [123] Best Time to Buy and Sell Stock III
*/
// @lc code=start
class Solution {
public:
int maxProfit(vector<int>& prices) {
int N = prices.size();
if(N <=0 ) return 0;
// dpL[i] : [0:i]卖一次最大收益
// dpR[i] : [i:N-1]卖一次最大收益
vector<int> dpL(N,0);
vector<int> dpR(N,0);
int p = prices[0];
for(int i=1;i<N;i++){
p = min(p,prices[i]);
dpL[i] = max(dpL[i-1],prices[i] - p);
}
p = prices[N-1];
for(int i=N-2;i>=0;i--){
p = max(p,prices[i]);
dpR[i] = max(dpR[i+1],p - prices[i]);
}
// 枚举中间点
int ans = 0;
for(int i=0;i<N;i++){
//printf("<%d %d>\n",dpL[i],dpR[i]);
ans = max(ans,dpL[i]+dpR[i]);
}
return ans;
}
};
// @lc code=end