leetcode 123. 买卖股票的最佳时机 III
前情提要:
题意
给一个数组表示股票的价格,你每天最多持有一支股票,总共可以买最多两只股然后卖出,问最大利润
思路1
针对只能买两支股票,首先找出如果只买一支的最大利润对应的范围
接下来有两种可能
- 第一种,\([ans_{i1},ans_{i2}]\)不处理,其他区间找
- 第二种,\([ans_{i1},ans_{i2}]\)内部不是递增的,分成两部分,
- 第二种可以从[ans_i1,ans_i2]遍历,处理成对应下标左边最大和右边最小
这个思路可以画个折线图,比较好理解
代码1
class Solution
{
public:
int maxProfit(vector<int> &prices)
{
int n = prices.size();
int ans = 0;
int mx_prices = prices[n - 1];
int mx_i = n - 1;
int ans_i1 = -1, ans_i2 = -1;
for (int i = n - 2; i >= 0; i--)
{
if (mx_prices - prices[i] > ans)
{
ans_i1 = i;
ans_i2 = mx_i;
ans = mx_prices - prices[i];
}
if (prices[i] > mx_prices)
{
mx_i = i;
mx_prices = prices[i];
}
}
if (ans_i1 == ans_i2)
return 0;
// 第一种
mx_prices = prices[n - 1];
int ans1 = 0, ans2 = 0;
for (int i = n - 2; i >= ans_i2; i--)
{
mx_prices = max(mx_prices, prices[i]);
ans1 = max(ans1, mx_prices - prices[i]);
}
mx_prices = prices[ans_i1];
for (int i = ans_i1; i >= 0; i--)
{
mx_prices = max(mx_prices, prices[i]);
ans2 = max(ans2, mx_prices - prices[i]);
}
if (ans_i1 == ans_i2)
return ans + max(ans1, ans2);
// 第二种
vector<int> n_prices(prices.begin() + ans_i1, prices.begin() + ans_i2 + 1);
int nn = n_prices.size();
vector<int> l_mx(n_prices);
vector<int> r_mn(n_prices);
for (int i = 1; i < nn; i++)
l_mx[i] = max(l_mx[i], l_mx[i - 1]);
for (int i = nn - 2; i >= 0; i--)
r_mn[i] = min(r_mn[i], r_mn[i + 1]);
int ans3 = 0;
int Beg = n_prices[0], End = n_prices[nn - 1];
for (int i = 0; i < nn; i++)
ans3 = max(ans3, l_mx[i] - Beg + End - r_mn[i]);
return max(ans + max(ans1, ans2), ans3);
}
};
思路2 动态规划
针对每一天的状态,有以下五种:
- 啥都没买
- 买了第一支股票还没卖
- 卖了第一支股票
- 买了第二支股票还没卖
- 卖了第二支股票
啥都没买不需要管,接下来用四个变量存储:\(buy_{1},sell_{1},buy_{2},sell_{2}\)
\(buy_{1}\)的状态取最小的\(prices[i]\),或者说取最大的\(-prices[i]\)
\(sell_{1}\)取\(prices[i]-buy_{1}\)
\(buy_{2}sell_{2}\)的状态基于1的状态
代码如下:
class Solution
{
public:
Solution(vector<int> p)
{
cout << maxProfit(p);
}
int maxProfit(vector<int> &prices)
{
int n = prices.size();
int buy1 = -1e9, sell1 = -1e9, buy2 = -1e9, sell2 = -1e9;
for (int i = 0; i < n; i++)
{
buy1 = max(buy1, -prices[i]);
sell1 = max(sell1, prices[i] + buy1);
buy2 = max(buy2, sell1 - prices[i]);
sell2 = max(sell2, prices[i] + buy2);
}
return sell2;
}
};
但是如果不仅可以买两支股票呢
代码2
就是加了个buy和sell数组,不过我觉得其实可以用一个数组,不过两个数组好理解
没有测试例子,不确定k变大的时候有没有问题
int maxProfit2(vector<int> &prices)
{
int k = 2;
int n = prices.size();
// int buy1 = -1e9, sell1 = -1e9, buy2 = -1e9, sell2 = -1e9;
vector<int> buy(k + 1, -1e9), sell(k + 1, -1e9);
sell[0] = 0;
for (int i = 0; i < n; i++)
{
for (int j = 1; j < k; j++)
{
buy[j] = max(buy[j], sell[j - 1] - prices[i]);
sell[j] = max(sell[j], prices[i] + buy[j]);
buy[j + 1] = max(buy[j + 1], sell[j] - prices[i]);
sell[j + 1] = max(sell[j + 1], buy[j + 1] + prices[i]);
}
}
return sell[k];
}

leetcode 123. 买卖股票的最佳时机 III
浙公网安备 33010602011771号