Best Time to Buy and Sell Stock
只允许买一次,我们知道卖肯定在买之前,所以只要在考虑要不要卖之前,知道了前面天数的股票最低价就可以得到这一天卖的最大获利:时间复杂度O(n) 空间复杂度O(1)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
int ans = 0;
int buy = prices[0];
for(int i = 1;i<n;i++){
ans = max(prices[i]-buy, ans);
buy = min(buy, prices[i]);
}
return ans;
}
};
Best Time to Buy and Sell Stock II
可以卖无限次,其实就是贪心的玩法了,那当然就是股价下跌到最低点的时候买入,最高价的时候卖出了。
所以只要计算一天股票的上升部分的价格差,就是答案了。时间复杂度O(n) 空间复杂度O(1)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
int ans = 0;
for(int i = 1;i<n;i++){
if(prices[i]>prices[i-1]){
ans += prices[i]-prices[i-1];
}
}
return ans;
}
};
对于这种无限次交易,还有一种解法,用buy和sell记录当前买了或者卖了的状态的最大受益,用dp的方式不断更新这个状态值:
时间复杂度O(n) 空间复杂度O(1)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
int buy = -prices[0], sell = 0;
for(auto price:prices){
int t = sell;
sell = max(sell, buy+price);
buy = max(buy, t-price);
}
return sell;
}
};
Best Time to Buy and Sell Stock III
至多交易两次,可以dp的方式,从左往右和从右往左分别计算子数组至多交易一次的最大获利,那么最大获利就是左右子数组至多交易一次之和。时间复杂度O(n) 空间复杂度O(n)
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
vector<int> dp(n, 0);
int ans = 0;
int buy = prices[0];
for(int i = 1;i<n;i++){
ans = max(ans, prices[i]-buy);
buy = min(prices[i], buy);
dp[i] = ans;
}
vector<int> dp1(n, 0);
dp1[0] = 0;
ans = 0;
int sell = prices[n-1];
for(int i = n-2;i>=0; i--){
ans = max(ans, sell -prices[i]);
sell = max(prices[i], sell);
dp1[i] = ans;
}
ans = 0;
for(int i = 0;i<n-1;i++){
ans = max(ans, dp[i] + dp1[i]);
}
return ans;
}
};
解法二: 时间复杂度O(n) 空间复杂度O(1)
用数据,记录交易了0次和1次的最大获利maxprofit和最小价格minprice。
0的时候:最小价格即min(price)
1的时候:最小价格即min(price-minprice[0]),也就是把当前价格减去之前的获利,得到新的价格值。
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
int maxprofit[2] = {0, 0};
int minprice[2] = {prices[0], prices[0]};
for(int i = 1; i<n; i++){
for(int j = 1; j>=0; j--){
maxprofit[j] = max(maxprofit[j], prices[i]-minprice[j]);
minprice[j] = min(minprice[j],
prices[i]-(j>0?maxprofit[0]:0));
}
}
return maxprofit[1];
}
};
Best Time to Buy and Sell Stock IV
至多交易K次,这里当K>n/2那么就是无限次交易了,Best Time to Buy and Sell Stock II的解法即可,否则,解法3的通用表示。
时间复杂度O(n*k) 空间复杂度O(k)
class Solution {
public:
int maxProfit(int k, vector<int>& prices) {
int n = prices.size();
if(n==0 || k<=0) return 0;
if(k>n/2){
return unlimitProfit(prices);
}
vector<int> maxprofit(k, 0);
vector<int> minprice(k, prices[0]);
for(int i = 1; i<n; i++){
for(int j = k-1; j>=0; j--){
maxprofit[j] = max(maxprofit[j], prices[i]-minprice[j]);
minprice[j] = min(minprice[j],
prices[i]-(j>0?maxprofit[j-1]:0));
}
}
return maxprofit[k-1];
}
int unlimitProfit(vector<int> &prices){
int ans = 0;
for(int i = 1; i<prices.size(); i++){
if(prices[i]>=prices[i-1])
ans += prices[i]-prices[i-1];
}
return ans;
}
};
当然也可以用dp做啦,略。
Best Time to Buy and Sell Stock with Transaction Fee
贪心算法,计算连续上升的序列的截距之和,如果下降的截距大于fee,再进行一次交易可以获得更高的受益。
时间复杂度O(n),空间复杂度O(1)
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n = prices.size();
if(n==0) return 0;
int cur = prices[0];
int cur_min = prices[0];
int ans = 0;
for(int i = 1; i<n; i++){
if(prices[i]>=cur){
cur = prices[i];
} else {
if(cur-prices[i]>=fee){
if(cur-cur_min-fee>0)
ans += cur-cur_min-fee;
cur = cur_min = prices[i];
} else
cur_min = min(prices[i], cur_min);
}
}
if(cur-cur_min-fee>0)
ans += cur-cur_min-fee;
return ans;
}
};
无限次交易的通用解法:
class Solution {
public:
int maxProfit(vector<int>& prices, int fee) {
int n = prices.size();
if(n==0) return 0;
int hold = -prices[0], sell = 0;
for(auto price:prices){
int t = sell;
sell = max(sell, hold+price-fee);
hold = max(hold, t-price);
}
return sell;
}
};
Best Time to Buy and Sell Stock with Cooldown
class Solution {
public:
int maxProfit(vector<int>& prices) {
int n = prices.size();
if(n==0) return 0;
int sell[2] = {0, 0};
int buy[2] = {INT_MIN, INT_MIN};
for(int i = 0; i<n; i++){
int temp1 = buy[1];
int temp2 = sell[1];
buy[1] = max(buy[1], sell[0]-prices[i]);
sell[1] = max(sell[1], temp1+prices[i]);
buy[0] = temp1;
sell[0] = temp2;
}
return max(sell[0], sell[1]);
}
};