文章目录
算法详解4:买卖股票的最佳时机系列(上)
121.买卖股票的最佳时机

先阅读题目要求:
题目要求我们在某一天进行买入然后在之后的日子里面卖出从而获取最大利益。
那么我们只要获取一个最小值和一个最大值,然后让其相减即可得到最大利益。
那么上述操作可行吗?
我们将示例1代入到我们的方法中去获取了最小值1,但是最大值是7。因为不能使用7 - 1所以这种方法不可以。
那么还能怎么处理呢?
我们不获取卖出时候的价格,只获取卖出时候的利润即可。此时我们只需要处理最小值即可。
test
伪代码:
answer = max(answer, 此时卖出的利润);
细节处理:
因为可能在卖出时出现负数,所以answer初始化为0。
要求最小值所以可以给INT_MAX或0x3f3f3f3f
cpp
int maxProfit(vector<int>& prices) {
int answer = 0;
int minProfit = INT_MAX;
for (int i = 0; i < prices.size(); ++i) {
minProfit = std::min(minProfit, prices[i]);
answer = std::max(answer, prices[i] - minProfit);
}
return answer;
}
122.买卖股票的最佳时机II

先阅读题目要求:
题目要求我们在可以当天多次买卖股票,但是手中最多只能持有1股,然后获取最大利润。
和上一题不一样的是这道题可以当天多次买入和卖出。
那么该怎么处理呢?
由于题目要求我们手中只能持有1股,所以在每天结束的时候我们手中就会出现持有股票和没有股票两种状态。那么我们不需要纠结今天到底该不该交易,我们只需要关注今天结束时,这两种状态下我的'口袋里的现金'分别是多少。
因为利润可以理解为手中的现金余额。买入股票就是"花掉现金",所以利润减少;卖出股票就是"获得现金",利润增加。
使用变量:
cpp
int dp0 = 0, dp1 = -prices[0];
int newDp0 = max(dp0,dp1 + prices[i]);
int newDp1 = max(dp1,dp0 - prices[i]);
dp0 = newDp0;
dp1 = newDp1;
使用数组:
cpp
vector<vector<int>> dp(n,vector<int>(2));
dp[0][0] = 0;
dp[0][1] = -prices[0];
dp[i][0] = max(dp[i - 1][0],dp[i - 1][1] + prices[i]);
dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
完整代码(使用数组版)
cpp
int maxProfit(vector<int>& prices) {
int n = prices.size();
if (n == 0) return 0;
// dp[i][0] 无股票, dp[i][1] 有股票
vector<vector<int>> dp(n, vector<int>(2));
// 初始化
dp[0][0] = 0;
dp[0][1] = -prices[0];
for (int i = 1; i < n; i++) {
dp[i][0] = max(dp[i-1][0], dp[i-1][1] + prices[i]);
dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]);
}
return dp[n-1][0];
}
完整代码(使用变量版)
cpp
int maxProfit(vector<int>& prices) {
// 因为只能持有一支股票,那就不能在最低价进行抄底,
// 那么只能当天买入或者前一天买入然后当天卖出或者前一天卖出才能得到最高利润
int n = prices.size();
int dp0 = 0, dp1 = -prices[0];
for (int i = 0; i < n; ++i) {
// 每一天都计算一下最高利润然后给给dp0 和 dp1
int newDp0 = std::max(dp0, dp1 + prices[i]);
int newDp1 = std::max(dp1, dp0 - prices[i]);
dp0 = newDp0;
dp1 = newDp1;
}
return dp0;
}