LeetCode 309 买卖股票的最佳时机(含冷冻期)
题目链接:309. 买卖股票的最佳时机含冷冻期 - 力扣(LeetCode)
【解题思路】
-
1.确定dp数组含义
-
dp[i][j]
-
j的状态为
-
持有股票状态
-
状态一
-
今天买入股票,或者是之前就买入了股票然后没有操作,一直持有股票
-
j=0
-
-
-
不持有股票状态
-
状态二
-
保持卖出股票的状态
-
两天前就卖出了股票,度过了一天冷冻期
-
前一天就是卖出股票的状态,一直没操作
-
-
j=1
-
-
状态三
-
今天卖出股票
-
j=2
-
-
-
冷冻期状态
-
状态四
-
今天为冷冻期,但冷冻期状态不可以持续,只有一天
-
j=3
-
-
-
-
-
-
2.确定递推公式
-
达到买入股票的状态
-
状态一
-
dp[i][0]
-
1.前一天就是持有股票的状态
-
dp[i][0]=dp[i-1][0]
-
-
2.今天买入
-
1)前一天是冷冻期
-
状态四
-
dp[i-1][3]-prices[i]
-
-
-
2)前一天是保持卖出股票的状态
-
状态二
-
dp[i-1][1]-prices[i]
-
-
-
-
-
-
-
达到保持卖出股票的状态
-
状态二
-
dp[i][1]
-
1.前一天就是状态二
-
dp[i-1][1]
-
-
2.前一天是冷冻期
-
状态四
-
dp[i-1][3]
-
-
-
-
-
-
达到今天就卖出股票的状态
-
状态三
-
dp[i][2]
-
则昨天就一定是持有股票的状态
-
状态一
-
今天卖出
-
dp[i][2] = dp[i-1][0]+prices[i]
-
-
-
-
-
-
-
达到冷冻期状态
-
状态四
-
dp[i][3]
-
昨天一定是卖出股票的状态(状态三)
-
dp[i][3] = dp[i-1][2]
-
-
-
-
-
-
3.初始化dp数组
-
持有股票的状态
-
状态一
-
dp[0][0] = -prices[0]
-
第一天就持有股票,那一定是当天买入股票
-
-
-
-
保持卖出股票的状态
-
状态二
-
dp[0][1] = 0
-
根据递推公式的需要,我们只能初始化为0
-
-
-
-
今天就卖出股票
-
状态三
-
dp[0][2] = 0
-
同上,根据公式的需要,只能初始化为0
-
-
-
-
-
4.确定遍历顺序
-
从递推公式可以看出dp[i]都是由dp[i-1]推导出来,所以一定是从前向后遍历
-
-
5.举例推导dp数组
【解题步骤】
-
1.如果prices的长度为0,直接返回0
-
2.创建一个长度为prices.length和4的数组
-
3.初始化dp[0][0]
-
4.遍历数组
-
递推公式
-
-
5.返回状态二,状态三,状态四的最大值
【代码部分】
class Solution {
public int maxProfit(int[] prices) {
int len = prices.length;
if(len == 0)return 0;
int[][] dp = new int[len][4];
dp[0][0] = -prices[0];
for (int i = 1; i < len ; i++) {
dp[i][0] = Math.max(dp[i-1][0],Math.max(dp[i-1][3]-prices[i],dp[i-1][1]-prices[i]));
dp[i][1] = Math.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 Math.max(dp[len-1][3],Math.max(dp[len-1][1],dp[len-1][2]));
}
}
LeetCode 714 买卖股票的最佳时机(含手续费)
题目链接:714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)
【解题思路】
-
1.确定dp数组含义
-
dp[i][0]表示第i天持有股票所得到的最大现金
-
dp[i][1]表示第i天不持有股票所得到的最大现金
-
求的结果是dp[len-1][0]和dp[len-1][1]中的最大值
-
-
2.确定递推公式
-
第i天持有股票
-
dp[i][0] = max(dp[i-1][0],dp[i-1][1]-price[i])
-
第i-1天就持有股票,那么就保持现状,所得现金就是昨天持有股票的所得现金 即:dp[i - 1][0]
-
第i天买入股票,所得现金就是买入今天的股票后所得现金即:dp[i-1][1]-prices[i]
-
跟上一题唯一的区别就是可以买入多次,所以是前一天没有股票的现金减去买股票花的钱
-
-
-
-
第i天不持有股票
-
dp[i][1] = max(dp[i-1][1],price[i]+dp[i-1][0]-fee)
-
第i-1天就不持有股票,那么就保持现状,所得现金就是昨天不持有股票的所得现金 即:dp[i - 1][1]
-
第i天卖出股票,所得现金就是按照今天股票价格卖出后所得现金即:prices[i] + dp[i - 1][0]
-
注意要减去手续费fee
-
-
-
-
-
3.初始化dp数组
-
dp[0][0]= -price[0]
-
表示第一天买入股票(持有股票)
-
-
dp[0][1] = 0
-
表示第一天不买入股票(不持有股票)
-
-
-
4.确定遍历顺序
-
从递推公式可以看出dp[i]都是由dp[i-1]推导出来,所以一定是从前向后遍历
-
-
5.举例推导dp数组
【解题步骤】
-
1.如果prices为空或者prices长度为0,直接返回0
-
2.新建一个二维dp数组,长度为price的长度和2
-
3.初始化dp[0][0]=-prices[0];dp[0][1]=0
-
4.从前往后遍历数组
-
递推公式
-
-
5.返回dp[length-1][1]
【代码部分】
class Solution {
public int maxProfit(int[] prices, int fee) {
if(prices == null || prices.length == 0)return 0;
int [][] dp = new int[prices.length][2];
dp[0][0]=-prices[0];
dp[0][1]=0;
for(int i = 1 ; i < dp.length ; i++){
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1]-prices[i]);
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0]+prices[i] - fee);
}
return dp[prices.length - 1][1];
}
}