这篇page是针对leetcode上的123.买股票的最佳时机Ⅲ所写的。小尼先简单的说明一下这道题的意思,就是我们给定一个数组,它的第i个元素表示的是一支股票在第i天的价格,我们需要设计一个算法表示我们如果进行两次交易我们可以得到的最大金额。
其实这道题也是接着小尼之前所写的几道题来的,小尼先做一个简单的分析,我们在这道题中还是取一个最优解的思想,小尼在这里也是同样给出动态规划五部曲:
1、确定dp数组以及下标的含义:
我们将它分为五个状态:0、没有操作
1、第一次买入
2、第一次卖出
3、第二次买入
4、第二次卖出
我们这里利用二维数组进行对应的表示:dp[i][j]中i表示为第i天,j为0-4的五个状态,dp[i][j]就是表示第i天状态j下所剩的最大现金。
2、确定递推公式:
我们首先对dp[i][1]也就是第一次买入的状态进行分析,我们一共有两种情况,第一种就是我们第i天买入了股票dp[i][1] = dp[i-1][0] - prices[i];第二种情况就是第i天没有操作,而是直接沿用前一天买入的情况dp[i][1] = dp[i-1][1];所以我们可以推出dp[u][1] = max(dp[i - 1][0] - prices[i], dp[i - 1][1])
同理我们可以推出dp[i][2] = max(dp[i][1] + prices[i], dp[i - 1][2]) ; dp[i][3] = max(dp[i - 1][3],dp[i ][2] - prices[i]) ; dp[i][4] = max(dp[i - 1][4],dp[i][3] + prices[i])
3、如何对dp数组进行初始化:
我们第0天没有做任何的操作,那么我们就是直接对我们的dp[0][0] = 0; 然后我们第0天对第一次做买入的操作,就是dp[0][1] = -prices[0];同理我们也需要对第二次做一个买入的操作,即dp[0][2] = 0;我们一定需要知道的是虽然我们在这里对我们的初始化了一个负值的操作,但是在我们的代码中我们会比较我们的大小的一个操作,所以我们只需要直接比较即可,接下来,小尼拉一下解决这道题的代码:
- class Solution {
- public int maxProfit(int[] prices) {
- int len = prices.length;
-
- if(prices.length == 0) return 0;
-
- int[][] dp = new int[len][5];
- dp[0][1] = -prices[0];
- dp[0][3] = -prices[0];
-
- for(int i = 1; i < len ; i++){
- dp[i][1] = Math.max(dp[i-1][1],-prices[i]);
- dp[i][2] = Math.max(dp[i-1][2],dp[i][1] + prices[i]);
- dp[i][3] = Math.max(dp[i-1][3],dp[i][2] - prices[i]);
- dp[i][4] = Math.max(dp[i-1][4],dp[i][3] + prices[i]);
- }
- return dp[len - 1][4];
- }
- }
小尼对上面的代码做一个简单的分析,其实我们这里就是进行了一个买入和卖出的操作,小尼直接先说一下买入的操作,我们在买入的时候我们就会有两种选择,第一种就i是我们直接就是延续我们上一次买入了的操作,第二种就是我们还没有买入,我们直接拿我们没有买入的钱取直接进行购买,在这里因为我们购买需要花钱,所以我们直接就是拿今天没有持股票的钱直接减去我们的prices[i]即可,然后就是小尼接着说卖出的操作,我们会有的状态也是有两种,第一种就是我们延续上一次我们就已经卖出的钱,第二种就是我们在今天将我们已经持有的物品进行对应对卖出,我们卖出之后我们是挣钱的,所以我们直接就是加上我们的prices[i]即可,我们不管有多少次可以进行持股,我们只需要不断的操作即可
希望上面的代码可以帮助到小伙伴们~~~