188.买卖股票的最佳时机IV
视频讲解:https://www.bilibili.com/video/BV16M411U7XJ
https://programmercarl.com/0188.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BAIV.html
思路
#define max(a, b) ((a) > (b) ? (a) : (b))
int maxProfit(int k, int* prices, int pricesSize) {
if(pricesSize == 0){
return 0;
}
int dp[pricesSize][2 * k + 1];
memset(dp, 0, sizeof(int) * pricesSize * (2 * k + 1));
for (int j = 1; j < 2 * k; j += 2) {
dp[0][j] = -prices[0];
}
for (int i = 1;i < pricesSize; i++) {
for (int j = 0; j < 2 * k - 1; j += 2) {
dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] - prices[i]);
dp[i][j + 2] = max(dp[i - 1][j + 2], dp[i - 1][j + 1] + prices[i]);
}
}
return dp[pricesSize - 1][2 * k];
}
学习反思
动态规划解决的股票交易问题。代码中定义了一个max函数来取两个数中的最大值。然后定义了一个maxProfit函数,参数分别是k(交易次数限制)、prices(股票价格数组)、pricesSize(价格数组的大小)。函数首先判断如果pricesSize为0,直接返回0。然后定义了一个二维数组dp,大小为pricesSize行,2 * k + 1列。然后使用memset函数将dp数组全部初始化为0。接下来使用两个for循环来计算dp数组的值。第一个for循环用来初始化dp数组的第一行,偶数列的值都为0,奇数列的值都为-prices[0]。第二个for循环用来计算dp数组剩下的值。外层循环遍历pricesSize,内层循环遍历2 * k - 1。在循环体内,使用max函数分别更新dp[i][j+1]和dp[i][j+2]的值。其中dp[i][j+1]的更新规则是将前一天的dp[i-1][j+1]和dp[i-1][j] - prices[i]取最大值;dp[i][j+2]的更新规则是将前一天的dp[i-1][j+2]和dp[i-1][j+1] + prices[i]取最大值。最后返回dp[pricesSize-1][2 * k],即最后一天结束后的最大利润。
309.最佳买卖股票时机含冷冻期
本题加了一个冷冻期,状态就多了,有点难度,大家要把各个状态分清,思路才能清晰
视频讲解:https://www.bilibili.com/video/BV1rP4y1D7ku
https://programmercarl.com/0309.%E6%9C%80%E4%BD%B3%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E6%97%B6%E6%9C%BA%E5%90%AB%E5%86%B7%E5%86%BB%E6%9C%9F.html
思路
#define max(a, b) ((a) > (b) ? (a) : (b))
int maxProfit(int* prices, int pricesSize) {
if(pricesSize == 0){
return 0;
}
int dp[pricesSize][4];
memset(dp, 0, sizeof (int ) * pricesSize * 4);
dp[0][0] = -prices[0];
for (int i = 1; i < pricesSize; ++i) {
dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][1] - prices[i], dp[i - 1][3] - prices[i]));
dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
dp[i][2] = dp[i - 1][0] + prices[i];
dp[i][3] = dp[i - 1][2];
}
return max(dp[pricesSize - 1][1], max(dp[pricesSize - 1][2], dp[pricesSize - 1][3]));
}
学习反思
用动态规划解决股票买卖问题的函数。通过观察代码,可以看出代码中使用了一个二维数组dp来记录每一天的股票交易状态。首先,定义了一个宏函数max,用来取两个数的最大值。然后,函数开始对dp数组进行初始化,将其全部设置为0。接下来,通过一个for循环,遍历每一天的股票价格。在每一天,根据前一天的交易状态,更新当天的交易状态。dp[i][0]表示在第i天持有股票时的最大收益,它可以由以下三种情况转移得到:第一种情况是继续保持空仓,即dp[i-1][0];第二种情况是在第i-1天卖出,并在第i天买入,即dp[i-1][1]-prices[i];第三种情况是在第i-1天卖出,并在第i天买入,即dp[i-1][3]-prices[i]。这三种情况中取最大值作为dp[i][0]的值。dp[i][1]表示在第i天不持有股票,且处于冷冻期时的最大收益,它可以由两种情况转移得到:第一种情况是继续保持空仓,即dp[i-1][1];第二种情况是在第i-1天卖出股票,即dp[i-1][3]。这两种情况中取最大值作为dp[i][1]的值。dp[i][2]表示在第i天不持有股票,且不处于冷冻期时的最大收益,它可以由以下情况转移得到:第一种情况是在第i-1天持有股票,且在第i天卖出,即dp[i-1][0]+prices[i];第二种情况是在第i-1天处于冷冻期,即dp[i-1][2]。这两种情况中取最大值作为dp[i][2]的值。dp[i][3]表示在第i天不持有股票且处于冷冻期时的最大收益,它可以由以下情况转移得到:第一种情况是在第i-1天不持有股票,且不处于冷冻期,即dp[i-1][1];第二种情况是在第i-1天不持有股票且处于冷冻期,即dp[i-1][2]。这两种情况中取最大值作为dp[i][3]的值。最后,返回dp数组中的最大值,即是最大收益。
714.买卖股票的最佳时机含手续费
视频讲解:https://www.bilibili.com/video/BV1z44y1Z7UR
https://programmercarl.com/0714.%E4%B9%B0%E5%8D%96%E8%82%A1%E7%A5%A8%E7%9A%84%E6%9C%80%E4%BD%B3%E6%97%B6%E6%9C%BA%E5%90%AB%E6%89%8B%E7%BB%AD%E8%B4%B9%EF%BC%88%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%EF%BC%89.html
思路
#define max(a, b) ((a) > (b) ? (a) : (b))
int maxProfit(int* prices, int pricesSize, int fee) {
int dp[pricesSize][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for (int i = 1; i < pricesSize; ++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] - fee);
}
return dp[pricesSize - 1][1];
}
学习反思
解决股票买卖问题的动态规划解法。其中,prices是一个整数数组,表示一系列股票的价格,pricesSize表示数组的大小,fee表示交易手续费。该算法使用一个二维数组dp来记录每一天的最大利润。dp[i][0]表示第i天持有股票时的最大利润,dp[i][1]表示第i天不持有股票时的最大利润。算法的思路是从第一天开始,对于每一天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]-fee)。最后,返回dp[pricesSize-1][1]即为最终的最大利润。算法的时间复杂度是O(n),
总结
加油!!!