目录
122. 买卖股票的最佳时机 II - 力扣(LeetCode)
188. 买卖股票的最佳时机 IV - 力扣(LeetCode)
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)
121. 买卖股票的最佳时机 - 力扣(LeetCode)

解析:
动态规划问题解决步骤可分为以下几点,可以帮我更好的理清逻辑
1.状态表示(根据题目要求 + 经验)
本题要求我们只能交易一只股票,根据经验 我们可以这样表示:dp[i] = d[i - 1] + prices[ i ] 但是这样不行的,我们可以有两种状态 :买入 or 卖出 。我们可以画出这两种状态的转化图。

根据状态图,我们可以得到多状态表示
dp[ i ] [ 0 ] : 当前我手里没有股票,处于买入状态,此时我手中的钱。
dp[ i ] [ 1 ] :当前我手里有股票,处于卖出状态,此时我手里的钱。
2.状态转移方程
依据这个图 
dp [ i ] [ 0 ] = max(dp[ i - 1] [ 0] , dp[i - 1] [ 1] + prices[ i - 1 ]);
dp[i ] [ 1] = max(dp[ i ] [ 1 ] , -prices[ i - 1 ]);
创建一个二维数组,0 / 1 表示当前我手中的股票状态:0代表我手里没有股票,1代表我有股票。
3.初始化
本题需要加上一个虚拟节点,
第0天手上没有股票 :dp[ 0] [0] = 0;
第0天手上有股票:dp[0][1] = -prices[0]; 买了一只股票,手中余额为负数。
4.填表顺序
从左往右。
5.返回值: 返回dp数组中最大的元素.
6.编写代码:
class Solution {
//动态规划:多状态dp
public int maxProfit(int[] prices) {
int n = prices.length;
if(n == 1) return 0;
int[][] dp = new int[n+1][2];
dp[0][0] = 0; dp[0][1] = -prices[0];
int ret = Integer.MIN_VALUE;
for(int i = 1; i <= n; i++){
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] + prices[i-1]);
dp[i][1] = Math.max(dp[i-1][1], - prices[i-1]);
ret = Math.max(dp[i][0],ret);
}
return Math.max(dp[n][0],dp[n][1]);
}
}
122. 买卖股票的最佳时机 II - 力扣(LeetCode)

1.状态表示(根据题目要求 + 经验)
上来就定义:dp[i] : 表示第i天获得的最大利润。
dp[i] 等于前一天的利润加上当天的利润,但是当天的利润怎么求?应该等于当前价格 - 买入价格。但是发现定义的这个状态表示不能记录买入的价格。所以应该换一种思路,这样的状态表示是不合适的。
股票的状态有买入和卖出。可以定义两个状态表示。

2.状态转移方程

3.初始化

4.填表顺序
从左往右。
5.返回值: f数组 或者 g 数组的最大值
6.编写代码
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
int[] f = new int[n+1]; //处于买入状态的利润
int[] g = new int[n+1]; //处于卖出状态的利润
f[0] = -prices[0];
int ret = 0;
for(int i = 1; i <= n; i++){
f[i] = Math.max(f[i-1],g[i-1] - prices[i-1]);
g[i] = Math.max(g[i-1],f[i-1] + prices[i-1]);
ret = Math.max(ret , Math.max(f[i],g[i]));
}
return ret;
}
}
188. 买卖股票的最佳时机 IV - 力扣(LeetCode)

1.状态表示
本题为多状态转移方程,定义状态表示

2.状态转移方程

3,代码
class Solution {
public int maxProfit(int k, int[] prices) {
int INT = 0x3f3f3f3f;
int n = prices.length;
k = Math.min( k, n / 2); //优化,k 大于 n 的情况
int[][] f = new int[n+1][k+1];
int[][] g = new int[n+1][k+1];
for(int j = 0; j <= k; j++){
f[0][j] = -INT;
g[0][j] = -INT;
}
f[0][0] = -prices[0] ; g[0][0] = 0;
for(int i = 1; i <= n; i++){
for(int j = 0; j <= k; j++){
f[i][j] = Math.max(f[i-1][j],g[i-1][j] - prices[i-1]);
g[i][j] = g[i-1][j];
if(j - 1 >= 0)
g[i][j] = Math.max(g[i][j],f[i-1][j-1] + prices[i-1]);
}
}
int ret = 0;
for(int j = 0; j <= k; j++){
ret = Math.max(ret, g[n][j]);
}
return ret;
}
}
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode)

1.状态表示
此题与 122题不差异,只不过在每次交易时多支付一次手续费。

2.状态转移方程

3.初始化

4.填表顺序
从左往右。
5.返回值: f数组 或者 g 数组的最大值
6.编写代码
class Solution {
public int maxProfit(int[] p, int fee) {
int n = p.length;
int[] f = new int[n];
int[] g = new int[n];
f[0] = -p[0];
for(int i = 1;i < n; i++){
f[i] = Math.max(f[i-1],g[i-1] - p[i]);
g[i] = Math.max(g[i-1],f[i-1] + p[i] - fee);
}
return Math.max(f[n-1],g[n-1]);
}
}

2559

被折叠的 条评论
为什么被折叠?



