leetcode买卖股票系列
- 121. Best Time to Buy and Sell Stock(easy)
- 122. Best Time to Buy and Sell Stock II(easy)
- 123. Best Time to Buy and Sell Stock III(hard)
- 188. Best Time to Buy and Sell Stock IV(hard)
- 309. Best Time to Buy and Sell Stock with Cooldown(medium)
解答
- 第121,122题简单,不表
第123题,暴力(自己想出来的,但是1200ms = =!)/ dp / trick
class Solution { public: /* 思路: 遍历数组,当前处于i位置的时候,分别求[0~i]买卖一次股票的最大收益和[i+1~end]买卖一次股票的最大收益,求和为i位置的时候的最大收益 复杂度: 时间:O(N^2) 空间:O(1) 爆炸:测试时间1000多ms */ int maxProfit(vector<int>& prices) { if(prices.size()==0) return 0; int res = 0; for(int i=0;i<prices.size();i++) { int left = maxProfitOnce(prices, 0, i); int right = maxProfitOnce(prices, i+1, prices.size()-1); res = max(res, left+right); } return res; } int maxProfitOnce(vector<int>& prices, int start, int end) { int max_ = prices[end]; int res = 0; for(int i=end-1;i>=start;i--) { if(prices[i]<max_) res = max(res, max_-prices[i]); else max_ = prices[i]; } return res; } };
class Solution {
public:
/*
思路:
dp解法,建立一个二维dp数组
dp[k][ii]表示最多k次交易,到prices[ii]为止(不包含prices[ii])所能获得的最大收益
则dp[k][ii] = max(dp[k][ii-1], prices[ii]-prices[jj]+dp[k-1][jj])其中jj属于[0, ii-1]闭区间,推导可得
dp[k][ii] = max(dp[k][ii-1], prices[ii]+max(dp[k-1][jj]-prices[jj]))其中jj属于[0, ii-1]闭区间
dp[1][ii] = 0
dp[k][1] = 0
复杂度:
时间:O(k*N)
空间:O(k*N)
*/
int maxProfit(vector<int>& prices) {
int res = 0;
if(prices.size()==0)
return 0;
else
{
int k = 2;
vector<vector<int>> dp(k+1, vector<int>(prices.size(), 0));
for(int kk=1;kk<=k;kk++)
{
int maxTemp = dp[kk-1][0] - prices[0];
for(int ii=1;ii<prices.size();ii++)
{
dp[kk][ii] = max(dp[kk][ii-1], prices[ii]+maxTemp); //左
res = max(res, dp[k][ii]);
maxTemp = max(maxTemp, dp[kk-1][ii]-prices[ii]); //上
}
}
}
return res;
}
};
class Solution {
public:
/*
思路:
优化一下dp解法,建立一个一维dp数组
复杂度:
时间:O(k*N)
空间:O(N)
*/
int maxProfit(vector<int>& prices) {
int res = 0;
if(prices.size()==0)
return 0;
else
{
int k = 2;
vector<int> dp(prices.size(), 0);
for(int kk=1;kk<=k;kk++)
{
int maxTemp = dp[0] - prices[0];
for(int ii=1;ii<prices.size();ii++)
{
int tempTop = dp[ii];
dp[ii] = max(dp[ii-1], prices[ii]+maxTemp); //左
res = max(res, dp[ii]);
maxTemp = max(maxTemp, tempTop-prices[ii]); //上
}
}
}
return res;
}
};
class Solution {
public:
/*
思路:
初始手上就0块钱,buy1表示我需要向别人借钱来买入这个股票prices[i],所以我实际上是欠别人buy1块钱,我想让欠的钱约少越好,则需要最大化buy1,因为buy1是负的 -> buy1 = max(buy1, -prices[i]);
sell1表示我先在手上有buy1块钱,想以prices[i]卖掉我手上这支股票,卖掉后我剩下sell1块钱,当然也是越大越好,sell1 = max(sell1, buy1+prices[i]);
buy2表示我现在手上有sell1块钱,我想买入prices[i],买入后我手上有buy2块钱,也希望buy2越大越好,buy2 = max(buy2, sell1+prices[i]);
sell2表示我现在手上有buy2块钱,想以prices[i]卖掉我手上这支股票,卖掉后我剩下sell2块钱,希望也是sell2越大越好
*/
int maxProfit(vector<int>& prices) {
if(prices.size()==0)
return 0;
int buy1 = INT_MIN, sell1 = 0, buy2 = INT_MIN, sell2 = 0;
//这么初始化的原因是:
//buy1设最小值则我刚开始必买入
//sell1设为0,那么如果卖出后是亏的我就相当于之前不买
//类似设置buy2和sell2
for(int i : prices)
{
buy1 = max(buy1, -i);
sell1 = max(sell1, buy1+i);
buy2 = max(buy2, sell1-i);
sell2 = max(sell2, buy2+i);
}
return sell2;
}
};
第188题实际上就是第123题dp的解法,不对!dp这样子做会超时!!还得考虑k>=prices.size()/2的时候就转换为问题122的贪心算法!!!
class Solution { public: int maxProfit(int k, vector<int>& prices) { int res = 0; if(k<=0 || prices.size()==0) return 0; if(k>=prices.size()/2) //若次数大于size的一般则相等于无限次数的买入卖出了 { for(int i=0;i<prices.size()-1;i++) { if(prices[i+1]>prices[i]) res += prices[i+1]-prices[i]; } return res; } else { vector<int> dp(prices.size(), 0); for(int kk=1;kk<=k;kk++) { int maxTemp = dp[0] - prices[0]; for(int ii=1;ii<prices.size();ii++) { int temp = dp[ii]; dp[ii] = max(dp[ii-1], prices[ii]+maxTemp); maxTemp = max(maxTemp, temp-prices[ii]); res = max(res,dp[ii]); } } } return res; } };