引言
股票问题是dp问题中很重要的一类问题,其主要思想是每次分为持有股票和持有现金两个状态,这两个状态分别可以从前一天保持和当天改变得到。
基本方法 :
dp[i][0][k] 表示在第i天,持有现金的情况,且此时还可以进行的交易次数数k
dp[i][1][k] 表示在第i天,持有股票的情况,且此时还可以进行的交易次数数k
初始值设定:
一般情况下,我个人喜欢对dp进行padding,也就是构造n+1
行2列的dp。
初始时,不可能持有股票,因此dp[0][1] = float('-inf')
。而不持有股票时,收益为0dp[0][0] = 0
。
对于转手次数,k = 0时,不可能发生交易。因此dp[i][0][0], dp[i][0][1] = 0, float('-inf')
转移方程:
每次进行转移时:
dp[i][0][k] = max(dp[i-1][0][k], dp[i-1][1][k]+prices[i])
dp[i][1][k] = max(dp[i-1][1][k], dp[i-1][0][k-1]-prices[i])
注意,是在买入时候,减少次数
只能交易一次的股票
因为只能交易一次,因此我们可以使用不断寻找最小值的思路。维护一个最小的minPrice,和一个当前的最大收益maxProfix。
public int maxProfit(int[] prices) {
int n = prices.length;
int max = 0;
int min = prices[0];
for (int i = 1;i<n;i++){
if(min>prices[i]){
min = prices[i];
}else{
max = Math.max(prices[i]-min, max);
}
}
return max;
}
}
可以无穷交易的
对于交易次数没有限制了。可以尝试交易无穷次。因为可以使用dp数组,当然也可以在空间上进行升级。
class Solution {
public int maxProfit(int[] prices) {
// 关键在于注意边界条件,在第一天的时候持有股票是负数
int n = prices.length;
int[] dp = new int[2];
dp[0] = 0; // 不持有股票
dp[1] = -prices[0]