前言
昨天补知识点补的太晚了,导致没有更新,所以今天更新两期噜
我们再回忆一下前两题我们做的买卖股票问题
T121 这里是买卖股票一次,求最大利润,可以使用贪心也可以使用动规,但是注意只能买卖一次,定义两个状态,一个是持有状态,一个是卖出状态
dp[i][0] = Math.max(dp[i - 1][0], -prices[i]);
dp[i][1] = Math.max(dp[i - 1][0] + prices[i], dp[i - 1][1]);T122 这里就是在上一题的基础上可以买卖股票多次,递推公式就是在上一个基础上修改一下将持有状态从(0就是初始的钱数)0-peices[i]修改成了上一次卖出的状态减去股票的价值
LeetCode T123 买卖股票的最佳时机III
题目链接:123. 买卖股票的最佳时机 III - 力扣(LeetCode)
题目思路:
这题的意思是让我们操作买卖两次股票,其实我们可以选择多定义两次状态来表示第二次的买卖持有和卖出状态,下面我们使用动规五部曲进行分析
1.明确动规数组含义
这里我们定义四种状态
dp[i][1]表示第一次持股的状态
dp[i][2]表示第一次卖出股票的状态
dp[i][3]表示第二次持股的状态
dp[i][4]表示第二次卖出的状态
有人可能会说为啥没有第一次没买的状态,其实是有的,就是dp[i][0],我们不去操作他罢了
2.明确递推公式
第一次持股可以由前一次就是第一次持股产生,也可以由前一次不持股产生
dp[i][1] = Math.max(dp[i-1][1],-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]);
3.初始化数组
由于dp[i][?]的状态都是由前一个产生的,所以我们初始化dp[0][?]
dp[0][1]初始化为-price[0]
dp[0][2]初始化为0,可以理解为买入再卖出
dp[0][3]初始化为-price[0],可以理解为买入卖出再买入
同理dp[0][4]初始化为0
4.遍历顺序
顺序遍历因为后面的数据由前面的产生.
5.打印dp数组排错
题目代码:
class Solution { public int maxProfit(int[] prices) { int[][] dp = new int[prices.length][5]; 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][1] = Math.max(dp[i-1][1],-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]; } }
LeetCode T188 买卖股票的最佳时机IV
题目链接:188. 买卖股票的最佳时机 IV - 力扣(LeetCode)
题目思路:
1.明确动规数组含义
我们知道一次买入和卖出可以定义5个状态(包含无操作状态)
那么k次买入与卖出就得有(2*k+1)个状态
dp仍然表示的是目前的最大钱数
dp[i][j]表示第i天状态j所剩下的最大现金
2.明确递推公式
dp[i][j+1]表示持有的状态(可以带入到上面两次的情况进行检验)
dp[i][j+2]表示卖出的状态
dp[i][j+1] = Math.max(dp[i-1][j+1],dp[i-1][j]-prices[i]);
dp[i][j+2] = Math.max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]);
3.初始化数组
初始化数组我们发现奇数状态都是-prices[0],偶数状态都是0
可以理解为当天多次买入卖出
4.遍历顺序
从前向后遍历,因为后面的状态取决于前面的状态
5.打印dp数组排错
和上面的类似
题目代码:
class Solution { public int maxProfit(int k, int[] prices) { int dp[][] = new int[prices.length][2*k+1]; for(int j = 1;j<k*2;j+=2){ dp[0][j] = -prices[0]; } for(int j = 0;j<2*k-1;j+=2){ for(int i = 1;i<prices.length;i++){ dp[i][j+1] = Math.max(dp[i-1][j+1],dp[i-1][j]-prices[i]); dp[i][j+2] = Math.max(dp[i-1][j+2],dp[i-1][j+1]+prices[i]); } } return dp[prices.length-1][2*k]; } }