买卖股票
核心思路
- 这道题的核心思路是动态规划,定义一个二维数组
dp[i][j],其中 i 表示第 i 天,j 表示是否持有股票(0 表示持有,1
表示不持有)。通过状态转移方程来更新这个数组,从而得到最大利润。
- 状态转移方程如下:
dp[i][0] = max(dp[i-1][0], dp[i-1][1] - prices[i]):第 i 天持有股票的最大利润
- 有两个推导逻辑
- 第
i-1 天已经持有股票,那么第 i 天继续持有,利润不变,即 dp[i-1][0]
- 第
i-1 天不持有股票,那么第 i 天买入股票,利润变为 -prices[i]
dp[i][1] = max(dp[i-1][1], dp[i-1][0] + prices[i]):第 i 天不持有股票的最大利润
- 有两个推导逻辑
- 第
i-1 天已经不持有股票,那么第 i 天继续不持有,利润不变,即 dp[i-1][1]
- 第
i-1 天持有股票,那么第 i 天卖出股票,利润变为 dp[i-1][0] + prices[i]
- 最终答案是
dp[n-1][1],即最后一天不持有股票的最大利润。
代码实现
java
复制代码
public static int maxProfit(int[] prices) {
//dp[i][0]: 下标为i的时候, 持有股票 赚的钱
//持有股票: 要么i-1就已经持有了, 要么i买入
//dp[i][1]: 下标为i的时候, 未持有, 那就延续i-1的, 如果持有, 就卖掉, 就是i-1[0] - price[i]
//
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for (int i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], -prices[i]);
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] + prices[i]);
}
return Math.max(dp[prices.length - 1][0], dp[prices.length - 1][1]);
}
买卖股票2
核心思路
- 同买卖股票逻辑
- 只是当计算持有的时候, 如果选择买入当天的, 需要用i-11减去i, 因为昨天是有可能有利润的
java
复制代码
public static int maxProfit1(int[] prices) {
int[][] dp = new int[prices.length][2];
dp[0][0] = -prices[0];
dp[0][1] = 0;
for (int i = 1; i < prices.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]);
}
return dp[prices.length - 1][1];
}
买卖股票3
核心思路
- 这道题可以买卖两次
- 总结一下, 每天一共有4种状态
- 第一次持有或买进
- 第一次未持有或卖出
- 第二次持有或买进
- 第二次未持有或卖出
- 递推dp
- dp[i][0]
- 如果当天未买入, 那就延续i-1[0]的值
- 如果当天买入了, 那值就是 - price[i]
- 取最大值
- dp[i][1]
- 如果当天未卖出, 那就延续i-1[1]的值
- 如果当天卖出了, 那值就= i-1[0] + price[i]
- dp[i][2]
- 如果当天未买入, 那就延续i-1[2]的值
- 如果当天买入了, 那值就是[i-1][1] - price[i]
- dp[i][3]
- 如果当天未买入, 那就延续i-1[3]的值
- 如果当天卖出了, 那值就是[i-1][2] + price[i]
java
复制代码
public static int maxProfit2(int[] prices) {
int[][] dp = new int[prices.length][4];
dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = -prices[0];
dp[0][3] = 0;
for (int i = 1; i < prices.length; i++) {
dp[i][0] = Math.max(dp[i - 1][0], -prices[i]);
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]);
}
return dp[prices.length - 1][3];
}