买卖股票问题
123.买卖股票的最佳时机III
解题思路:
- 本题最多可以买卖两次, 但是最多只能同时持有一个
- 定义四个状态:
第一次持有 | 第一次未持有 | 第二次持有 | 第二次未持有 - 根据定义的状态推导出递推公式
代码:
class Solution {
// 最多买卖两次, 但是不能同时持有多个
public int maxProfit(int[] prices) {
// dp: 第一次持有股票的状态 | 第一次未持有的状态 | 第二次持有股票的状态 | 第二次未持有的状态
int n = prices.length;
int[][] dp = new int[n][4];
dp[0][0] = -prices[0];
dp[0][1] = 0;
dp[0][2] = -prices[0];
dp[0][3] = 0;
for(int i=1; i<n; i++){
// 第一次持有
dp[i][0] = Math.max(0 - prices[i], dp[i-1][0]);
// 第一次未持有
dp[i][1] = Math.max(dp[i-1][0] + prices[i], dp[i-1][1]);
// 第二次持有
dp[i][2] = Math.max(dp[i-1][1] - prices[i], dp[i-1][2]);
// 第二次未持有
dp[i][3] = Math.max(dp[i-1][2] + prices[i], dp[i-1][3]);
}
return dp[n-1][3];
}
}
188.买卖股票的最佳时机啊IV
解题思路:
- 动态规划 --- 和上题一样, 不过本题是至多交易
k次 - 定义
dp数组: 有2*k个状态 - 注意需要初始化, 和递推的时候, 第一次买入的时候一定是
Math.max(-prices[i], dp[i-1][0]); - 根据dp数组定义推导出递推公式即可
代码:
class Solution {
// 最多买卖k次, 但是同时最多只能持有一只股票
public int maxProfit(int k, int[] prices) {
int n = prices.length;
int[][] dp = new int[n][2*k];
// 初始化
for(int i=0; i < 2*k; i++){
dp[0][i] = i % 2 == 0?-prices[0]:0;
}
for(int i=1; i < n; i++){
for(int j=0; j < 2*k; j++){
if(j == 0) dp[i][j] = Math.max(-prices[i], dp[i-1][0]);
else {
dp[i][j] = j % 2 == 0?Math.max(dp[i-1][j-1]-prices[i], dp[i-1][j]):Math.max(dp[i-1][j-1] + prices[i], dp[i-1][j]);
}
}
}
return dp[n-1][2*k-1];
}
}