dp[i][j] i是天数,j是状态,0代表未持有股票,1代表持有股票,2代表冷冻期
-prices[i]代表买这一天的股票花的钱
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
if(n == 0) return 0;
int[][] dp = new int[n + 1][4];
dp[0][0] = 0;
dp[0][1] = -prices[0];
dp[0][2] = 0;
for(int i = 1; i < n; i++) {
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][2]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
dp[i][2] = dp[i - 1][1] + prices[i];
}
return Math.max(dp[n - 1][0], dp[n - 1][2]);
}
}
同上一题,添加一个fee就OK
class Solution {
public int maxProfit(int[] prices, int fee) {
int n = prices.length;
if(n == 0) return 0;
int[][] dp = new int[n + 1][3];
dp[0][0] = 0;
dp[0][1] = -prices[0];
for(int i = 1; i < n; i++){
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
}
// for(int i = 1; i < n; i++) {
// System.out.println(dp[i][0] + " " + dp[i][1]);
// }
return dp[n - 1][0];
}
}
dp1[i] = max(dp1[i-1], prices[i] - min) 从前往后遍历,表示第1天到第i天之间的最大利润(通过是否在第i天卖出确认);
dp2[i] = max(dp2[i+1], max - prices[i]) 从后往前遍历,表示第i天到最后一天之间的最大利润(通过是否在第i天买进确认);
ans = max(dp1[i] + dp2[i]) 正好表示从第1天到最后一天经过两次交易的最大利润,我们的目标是找到令总利润最大的i。
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
if(n == 0) return 0;
int[] dp1 = new int[n + 1];
int[] dp2 = new int[n + 1];
int Min = prices[0], Max = prices[n - 1];
dp1[0] = 0;
dp2[n - 1] = 0;
for(int i = 1; i < n; i++) {
dp1[i] = Math.max(dp1[i - 1], prices[i] - Min);
Min = Math.min(Min, prices[i]);
}
for(int i = n - 2; i > 0; i--) {
dp2[i] = Math.max(dp2[i + 1], Max - prices[i]);
Max = Math.max(Max, prices[i]);
}
int ans = 0;
for(int i = 0; i < n; i++) {
ans = Math.max(ans, dp1[i] + dp2[i]);
}
return ans;
}
}
dp[i][j] 第i次交易,第j天的最大利润
localMax 即通过上次交易买入当前股票求max得到。
那么不难得到dp[i][j] = Math.max(dp[i][j - 1], prices[j] + localMax);
class Solution {
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if (k >= n / 2) { // 这种情况下该问题退化为普通的股票交易问题
int maxProfit = 0;
for (int i = 1; i < n; i++) {
if (prices[i] > prices[i - 1]) {
maxProfit += prices[i] - prices[i - 1];
}
}
return maxProfit;
}
int[][] dp = new int[k + 1][n + 1];
for(int i = 1; i <= k; i++) {
int localMax = -prices[0];
for(int j = 1; j < n; j++) {
dp[i][j] = Math.max(dp[i][j - 1], prices[j] + localMax);
localMax = Math.max(localMax, dp[i - 1][j] - prices[j]);
}
}
return dp[k][n - 1];
}
}