代码随想录算法训练营第五十天|123.买卖股票的最佳时机III 、188.买卖股票的最佳时机IV
2024-01-10 09:34:18
代码随想录算法训练营第五十天|123.买卖股票的最佳时机III 、188.买卖股票的最佳时机IV
买卖股票的最佳时机III
123.买卖股票的最佳时机III
文章讲解:https://programmercarl.com/0123.%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%BAIII.html
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iii/
视频讲解:https://www.bilibili.com/video/BV1WG411K7AR/
自己看到题目的第一想法
动态规划五步骤、使用持有和不持有来计算。
看完代码随想录之后的想法
因为最多有2次交持有和不持有,分了5种情况。
0.没有操作
1.第一次持有股票
2.第一次不持有股票
3.第二次持有股票
4.第二次不持有股票
dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
自己实现过程中遇到哪些困难
看过代码随想录后自己实现了一下,ac了。
public int maxProfit(int[] prices) {
// 确定dp数组以及下标含义:
// 持有和不持有,分了5种情况。
// 0. 没有操作
// 1. 第一次持有股票
// 2. 第一次不持有股票
// 3. 第二次持有股票
// 4. 第二次不持有股票
// dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
int[][] dp = new int[prices.length][5];
// 确定递推公式
// dp[i][0]可以忽略 都没有操作 = 0
// dp[i][1]第一次持有,可能是之前持有,可能是本次持有 dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0] - prices[i]);
// dp[i][2]第一次不持有,可能是之前不持有,可能是本次不持有(本次不持有要上次持有的最大值+本次卖出) dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1] + prices[i]);
// 确定初始化值
dp[0][0] = 0;
dp[0][1] -= prices[0];
dp[0][2] = 0;
dp[0][3] -= prices[0];
dp[0][4] = 0;
// 确定遍历顺序,从小打大
for(int i = 1; i < prices.length; i++){
dp[i][0] = dp[0][0];
// 第一次持有
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0] - prices[i]);
// 第一次不持有,在最大的第一次持有上
dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1] + prices[i]);
// 第二次持有,在最大的第一次不持有上计算
dp[i][3] = Math.max(dp[i-1][3],dp[i-1][2] - prices[i]);
// 第二次不持有,在上一次最大持有上计算
dp[i][4] = Math.max(dp[i-1][4],dp[i-1][3] + prices[i]);
}
return dp[prices.length - 1][4];
}
买卖股票的最佳时机IV
188.买卖股票的最佳时机IV
文章讲解: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
题目链接:https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-iv/
视频讲解:https://www.bilibili.com/video/BV16M411U7XJ/
自己看到题目的第一想法
和123.买卖股票的最佳时机III几乎一样,只是买具体买卖的次数用k来替换。
写代码的话就将k之前的情况分成2k+1种:
0. 没有操作
1.第一次持有股票
2.第一次不持有股票
3…第k次持有
4…第k次不持有
代码就把最佳时机III改吧改吧。
public int maxProfit(int k, int[] prices) {
// 确定dp数组以及下标含义:
// 持有和不持有,分了5种情况。
// 0.没有操作
// 1.第一次持有股票
// 2.第一次不持有股票
// 3......第k次持有
// 4......第k次不持有
// dp[i][j]中 i表示第i天,j为 [0 - 4] 五个状态,dp[i][j]表示第i天状态j所剩最大现金。
int[][] dp = new int[prices.length][2*k + 1];
// 确定初始化值
for(int i = 0; i < 2*k + 1; i++){
if(i % 2 == 1){
dp[0][i] -= prices[0];
}else{
dp[0][i] = 0;
}
}
// 确定遍历顺序,从小打大
for(int i = 1; i < prices.length; i++){
for(int j = 1; j < 2*k + 1; j++){
if(j % 2 == 0){
// 表示第j次不持有
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j - 1] + prices[i]);
}else{
// 表示第j次持有
dp[i][j] = Math.max(dp[i-1][j],dp[i-1][j-1] - prices[i]);
}
}
}
return dp[prices.length - 1][2*k];
}
看完代码随想录之后的想法
自己实现过程中遇到哪些困难
照着上一题改吧改吧完成。
今日收获&学习时长
对于股票问题有了进一步的认识,股票问题核心是理解第i天的持有状态,通过持有状态去推导最优值。
文章来源:https://blog.csdn.net/shanshe7934/article/details/135445024
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!