121、买卖股票的最佳时机1
dp[i][0]:第i天的时候不持有股票,手头最大金额
dp[i][1]:第i天的时候不持有股票,手头最大金额
递推公式:看注释
初始化:初始化第一天两个状态即可,后面都会更新
遍历顺序:看状态都是由前一个状态推出来的,自然是从前向后
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];
dp[0][0] = 0;
dp[0][1] = -prices[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],-prices[i]);
}
return dp[prices.length -1][0];
}
}
122、买卖股票的最佳时机2
修改递推公式即可:
当天持有状态 = (前一天持有,前一天不持有-当天价格)的最大值
dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i]);
java
class Solution {
public int maxProfit(int[] prices) {
/*/贪心算法
int res = 0;
for(int i = 1; i < prices.length; i++){
int wave = prices[i] - prices[i-1];
if(wave > 0) res += wave;
}
return res;
//*/
//*/动态规划
int[][] dp = new int[prices.length][2];
dp[0][0] = 0;
dp[0][1] = -prices[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][0];
//*/
}
}
123、买卖股票的最佳时机3
数组第二个维度表示: 1第一次持有,2第一次不持有。3第二次持有,4第二次不持有。
状态转移方程很容易能推到出来。需要注意的是初始化的时候可以当天买入当天卖出。
java
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][5];
dp[0][0] = 0;
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] = -prices[i];
//第i天的时候第一次持有
dp[i][1] = Math.max(dp[i-1][1], -prices[i]);
//第i天的时候第一次不持有
dp[i][2] = Math.max(dp[i-1][2],dp[i-1][1]+prices[i]);
//第i天的时候第二次持有
dp[i][3] = Math.max(dp[i-1][3], dp[i-1][2] - prices[i]);
//第i天的时候第二次不持有
dp[i][4] = Math.max(dp[i-1][4], dp[i-1][3] + prices[i]);
}
return Math.max(dp[prices.length -1][4],dp[prices.length-1][2]);
}
}