121题
给定一个数组prices
,其中prices[i]
是一支给定股票第i
天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。但是,你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例
- 输入:
prices = [7,1,5,3,6,4]
- 输出:
5
- 解释:在第2天(股票价格=1)的时候买入,在第5天(股票价格=6)的时候卖出,最大利润=6-1=5。注意利润不能是7-1=6,因为卖出价格需要大于买入价格;同时,你不能在买入前卖出股票。
解题思路
贪心法:设置一个买入的价格,每次遇到比买入价格大,就换掉。并且每次都要更新最大收益
public int maxProfit(int[] prices) {
int max=0;
int buy=prices[0];
for (int i = 1; i < prices.length; i++) {
max=Math.max(max,prices[i]-buy);
if (prices[i]<buy){
buy=prices[i];
}
}
return max;
}
其他的股票问题均可以使用动态规划解答
动态规划主要是解决两个问题:枚举状态和选择
股票问题的状态:
天数:i
允许交易的最大次数:k
用户账户当前状态(持有或者未持有股票):0,1
dp[i][k][0 or 1] //前面说了三个维度,自然dp数组也是三维的。dp表示利润
for(int i = 0;i < n;i++)
for(int j = 0;j < k;j++)
dp[i][j][0] 取优
dp[i][j][1] 取优//账户状态这个维度只有两种可能,就直接计算就好啦。
122题(k无限制)
给定一个数组prices
,其中prices[i]
表示某支股票第i
天的价格。在每一天,你可以决定是否购买和/或出售股票。你在任何时候最多只能持有一股股票。你也可以先购买,然后在同一天出售。返回你能获得的最大利润。
示例
- 输入:
prices = [7,1,5,3,6,4]
输出:7
解释:在第2天(股票价格=1)的时候买入,在第3天(股票价格=5)的时候卖出,这笔交易所能获得利润=5-1=4。随后,在第4天(股票价格=3)的时候买入,在第5天(股票价格=6)的时候卖出,这笔交易所能获得利润=6-3=3。总利润为4+3=7。 - 输入:
prices = [1,2,3,4,5]
输出:4
解释:在第1天(股票价格=1)的时候买入,在第5天(股票价格=5)的时候卖出,这笔交易所能获得利润=5-1=4。总利润为4。 - 输入:
prices = [7,6,4,3,1]
输出:0
解释:在这种情况下,交易无法获得正利润,所以不参与交易可以获得最大利润,最大利润为0。
解题思路
在这个问题中,我们使用动态规划来寻找最优解。我们定义一个二维数组dp
,其中dp[i][0]
表示第i
天交易完后手里没有股票的最大利润,而dp[i][1]
表示第i
天交易完后手里持有一支股票的最大利润。
根据题目描述,我们可以得到状态转移方程如下:
-
如果第
i
天没有股票(dp[i][0]
),那么有两种情况:- 第
i-1
天也没有股票,并且今天没有进行任何操作(即不买入也不卖出),所以dp[i][0] = dp[i-1][0]
。 - 第
i-1
天持有股票,但今天卖出了股票,所以dp[i][0] = dp[i-1][1] + prices[i]
(其中prices[i]
是第i
天的股票价格)。
取这两种情况中的较大值,即:
dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i])
。 - 第
-
如果第
i
天持有股票(dp[i][1]
),那么也有两种情况:- 第
i-1
天也持有股票,并且今天没有进行任何操作(即不卖出也不买入),所以dp[i][1] = dp[i-1][1]
。 - 第
i-1
天没有股票,但今天买入了股票,所以dp[i][1] = dp[i-1][0] - prices[i]
。
取这两种情况中的较大值,即:
dp[i][1] = Math.max(dp[i-1][1], dp[i-1][0] - prices[i])
。 - 第
注意,初始化时,dp[0][0]
应该是0(因为没有股票且没有进行任何交易),而dp[0][1]
应该是-prices[0]
(因为我们在第一天买入了一支股票)。
最后,答案就是dp[n-1][0]
,其中n
是股票价格的长度,表示最后一天交易完后手里没有股票的最大利润。
class Solution {
public int maxProfit(int[] prices) {
int[][] dp = new int[prices.length][2];//0为未持有,1为持有
dp[0][0] = 0;
dp[0][1] = 0 - 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];
}
}
714题(有费用)
买卖股票的最佳时机含手续费
给定一个整数数组 prices
,其中第 i
个元素是一支给定股票第 i
天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。
此外,你还需要支付交易费用,每次交易(买入或卖出)都需要支付一个固定的费用 fee
。
返回你可以从这笔交易中获取的最大利润。
示例 1:
输入: prices = [1, 3, 2, 8, 4, 9], fee = 2
输出: 8
解释: 能够达到的最大利润:
在此处买入 prices[0] = 1
在此处卖出 prices[3] = 8
在此处买入 prices[4] = 4
在此处卖出 prices[5] = 9
总利润: ((8 - 1) - 2) + ((9 - 4) - 2) = 8
解题思路
如果第i天不持有股票(dp[i][0]):
第i-1天也不持有股票,今天没有进行任何操作:dp[i][0] = dp[i-1][0]
第i-1天持有股票,今天卖出了股票,需要支付手续费:dp[i][0] = dp[i-1][1] + prices[i] - fee
取这两者中的较大值:
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i] - fee);
如果第i天持有股票(dp[i][1]):
第i-1天就持有股票,今天没有进行任何操作:dp[i][1] = dp[i-1][1]
第i-1天不持有股票,但今天买入了股票(注意:这里不直接考虑手续费,因为手续费是在卖出时支付的):dp[i][1] = dp[i-1][0] - prices[i]
取这两者中的较大值:
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][0] - prices[i]);
class Solution {
public int maxProfit(int[] prices, int fee) {
int[][] dp = new int[prices.length][2];//0为未持有,1为持有
dp[0][0] = 0;
dp[0][1] = 0 - 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] - fee);
dp[i][1] = Math.max(dp[i - 1][1],dp[i - 1][0] - prices[i]);
}
return dp[prices.length - 1][0];
}
}
309
题目描述
给定一个整数数组prices
,其中第i
个元素是一支给定股票第i
天的价格。设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
- 交易限制:你不能同时参与多笔交易(即你必须在再次购买前出售掉之前的股票)。
- 冷冻期:卖出股票后,你无法在第二天买入股票(即冷冻期为1天)。
示例
输入: [1,2,3,0,2]
输出: 3
解释: 对应的交易状态为: [买入, 卖出, 冷冻期, 买入, 卖出]
。
解题思路
通过定义一个二维数组 dp
来存储不同状态下的最大利润。
变量定义
int n = prices.length;
:获取输入股票价格数组的长度。int[][] dp = new int[n][3];
:定义一个二维数组dp
,其中dp[i][0]
表示第i
天不持有股票的最大利润,dp[i][1]
表示第i
天持有股票的最大利润,dp[i][2]
表示第i
天处于冷冻期的最大利润。
初始化
dp[0][0] = 0;
:第一天不持有股票时利润为 0,因为还没有进行任何买卖操作。dp[0][1] = -prices[0];
:第一天持有股票,意味着花费了prices[0]
的成本,所以利润为-prices[0]
。dp[0][2] = 0;
:第一天不可能处于冷冻期,所以利润为 0。
状态转移方程
-
dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1] + prices[i]);
:- 第
i
天不持有股票有两种情况:- 第
i - 1
天就不持有股票,利润为dp[i - 1][0]
。 - 第
i - 1
天持有股票,第i
天卖出,利润为dp[i - 1][1] + prices[i]
(卖出价格为prices[i]
)。
- 第
- 取这两种情况的较大值作为第
i
天不持有股票的最大利润。
- 第
-
dp[i][1] = Math.max(dp[i - 1][1], dp[i - 1][2] - prices[i]);
:- 第
i
天持有股票有两种情况:- 第
i - 1
天就持有股票,利润为dp[i - 1][1]
。 - 第
i - 1
天处于冷冻期,第i
天买入股票,利润为dp[i - 1][2] - prices[i]
(买入价格为prices[i]
)。
- 第
- 取这两种情况的较大值作为第
i
天持有股票的最大利润。
- 第
-
dp[i][2] = dp[i - 1][0];
:- 第
i
天处于冷冻期,说明第i - 1
天卖出了股票,所以第i
天的冷冻期利润等于第i - 1
天不持有股票的利润,即dp[i - 1][0]
。
- 第
最终结果
返回 Math.max(dp[n - 1][0], dp[n - 1][2])
,因为最后一天的最大利润可能是不持有股票(dp[n - 1][0]
)或者处于冷冻期(dp[n - 1][2]
)的情况,取两者中的较大值作为最终的最大利润。
class Solution {
public int maxProfit(int[] prices) {
if (prices == null || prices.length <= 1) {
return 0;
}
int n = prices.length;
// dp[i][0] 表示第 i 天不持有股票的最大利润
// dp[i][1] 表示第 i 天持有股票的最大利润
// dp[i][2] 表示第 i 天处于冷冻期的最大利润
int[][] dp = new int[n][3];
dp[0][0] = 0;
dp[0][1] = -prices[0];
dp[0][2] = 0;
for (int i = 1; i < n; 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][2] - prices[i]);
dp[i][2] = dp[i - 1][0];
}
return Math.max(dp[n - 1][0], dp[n - 1][2]);
}
}
标签:int,股票,问题,max,prices,dp,利润
From: https://www.cnblogs.com/clarencezzh/p/18402641