labuladong大神的详细讲解——股票问题
力扣股票问题-合集
采用穷举思想,就是把【所有的状态】都列举出来,再找出每个【状态】对应的【选择】。
我们要穷举所有的【状态】,穷举的目的是根据对应的【选择】更新状态。
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ... ...
dp[状态1][状态2][...] = 择优(选择1,选择2,...)
但是,并不是每天都可以任意选择这3种,因为:
这个问题的状态只有3个:
dp[i][k][0 or 1]
0 <= i <= n-1 n表示天数
1 <= k <= K 大K表示最多交易次数
此问题共有n × K × 2 种状态
for 0 <= i < n :
for 1 <= k <= K:
for s in {0,1}:
dp[i][k][s] = max(buy, sell, rest)
解释:今天我没有持有股票,因为:
1.我昨天也没持有,今天选择rest;
2.我昨天持有了,今天选择sell。
dp[i][k][0] = max( dp[i-1][k][0] , dp[i-1][k][1] + price[i] )
max( 选择rest , 选择sell )
解释:今天我持有股票,因为:
1.我昨天持有,今天选择rest;
2.我昨天没有,今天选择buy。
dp[i][k][1] = max( dp[i-1][k][1] , dp[i-1][k-1][0] - price[i] )
max( 选择rest, 选择buy )
一次买卖股票的最大利润
class Solution {
public int maxProfit(int[] prices) {
1.low初始值设为负无穷大,你品,你细品!
int low = Integer.MAX_VALUE;
2.返回值res初始设为0,因为总不能赔钱!
int res = 0;
3.从头遍历
for (int i = 0; i < prices.length; i++) {
3.1.滑动取出最小值
low = Math.min(low,prices[i]);
3.2.利用贪心算法,求出最大的值,并存入返回值
res = Math.max(prices[i]-low,res);
}
return res;
}
}
class Solution {
public int maxProfit(int[] prices) {
int day = prices.length;
int state = 2;
int[][] dp = new int[day+1][state];
1.考虑好特殊值
dp[0][0] = 0; 开始前1天,没有股票,利润为0
dp[0][1] = Integer.MIN_VALUE; 开始前1天,有股票,利润为负无穷大,表示不可能
for (int i = 1; i < day+1; i++) {
2.动态规划相互依赖
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],0-prices[i-1]);
}
return dp[day][0];
}
}
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
class Solution {
public int maxProfit(int[] prices) {
int day = prices.length;
int state = 2;
int[][] dp = new int[day+1][state];
1.特殊值考虑好
dp[0][0] = 0;
dp[0][1] = Integer.MIN_VALUE;
for (int i = 1; i < day+1; 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],dp[i-1][0] - prices[i-1]);
}
return dp[day][0];
}
}
class Solution {
public int maxProfit(int[] prices) {
int day = prices.length;
int res = 0;
for (int i = 1; i < day; i++) {
1.只要 正 的利润
res += Math.max(0,prices[i]-prices[i-1]);
}
return res;
}
}
class Solution {
public int maxProfit(int[] prices, int fee) {
int day = prices.length;
int state = 2;
1.建立动态数组 dp[i][0]表示,第i天 不持有股票,手中有多少钱
dp[i][1]表示,第i天 持有股票,手中有多少钱
int[][] dp = new int[day+1][state];
2.base case 第0天不持有股票, 手中有 0 元
第0天 持有股票, 手中有 负无穷大的 钱
防止误判,因为第1天 要在for 循环做判断
dp[0][0] = 0;
dp[0][1] = Integer.MIN_VALUE;
for (int i = 1; i < day+1; i++) {
表示第 i 天不持有股票, 手中有多少钱, 是前一天也没持有钱多, 还是把前一天的卖了 钱多 ?
dp[i][0] = Math.max(dp[i-1][0],dp[i-1][1] + prices[i-1]);
表示第 i 天 持有股票, 手中有多少钱, 是前一天也持有钱多, 还是前一天没有,今天买入 钱多 ?
dp[i][1] = Math.max(dp[i-1][1],dp[i-1][0] - prices[i-1]-fee);
}
return dp[day][0];
}
}