裸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
这篇博客探讨了LeetCode第123题《最佳买卖股票时机III》的解决方案。作者首先介绍了原始的O(N^2)动态规划解法,但注意到其在大数据量下无法通过。接着,作者提出了一个优化策略,通过枚举中间点将时间复杂度降低到O(N),并详细解释了如何利用两个一维动态规划数组dpL和dpR分别计算左右区间内买卖一次的最大收益。最后,通过遍历所有中间点,得到了整体的最大利润。这种方法显著提高了算法效率,适用于10^5级别的数据规模。
591

被折叠的 条评论
为什么被折叠?



