买股票
动归那点事
动态规范问题三要素:
DP方程
三种状态,天数,买卖次数,当前是否持有股票 DP[day][num][true] DP[day][num][false]
迁移方程
不操作:DP[day][num][True] = Math.max(DP[day-1][num][True]
卖出: DP[day-1][num-1][False] - prices[Daynow]) DP[day][num][False] = Math.max(DP[day-1][num][False]
买入 :DP[day-1][num][True] + prices[Daynow])
初始状态
对于Day = 0 ;收益一定为0 对于Day = 0 ; num = 1;不合法; 对于Day = 0; True不合法;
只允许交易一次,所以num为定值1,带入方程 DP[day][1][1] = Math.max(DP[day-1][1][1],DP[day-1][0][0] - prices[Daynow]) DP[day][1][False] = Math.max(DP[day-1][0][False],DP[day-1][1][1] + prices[Daynow]) 对于DP[day-1][0][0],意义为前day-1天,进行了0次交易,没持有股票的情况.很明显值肯定为 0 所以有程序:
var maxProfit = function(prices) {
var dp = Array.from(new Array(prices.length),()=>[])
dp[0][0] = [0];
dp[0][1] = - prices[0]
for (var 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];
};dp[i-1][0] 和 dp[i-1][1] 和 已知条件prices[i-1] —> dp[i][0] dp[i-1][1] 和 已知条件prices[i-1] —> dp[i][1] 所以就没必要通过数组存储两个变量存前置状态即可,加上特判代码如下:
允许多次交易,num为无限,带入方程 跟上一题的区别就在于DP[day-1][0][0],变成了DP[day-1][num][0],之前可以进行任意次交易,那在计算收益的时候把之前的收益加上即可
对于此题DP方程为三维的,拆分成DP_T和DP_F两个二维数组更方便管理 次题num为2;理论上应该再引入一个循环去处理num,但因为就循环两次,所以直接写两遍逻辑也可以
同理我们可以进行优化,抛弃DP数组存储:
跟第二题唯一的区别就是一个是__DP_F[i-1]__ ,一个是__DP_F[i-2]__
第二题的变种.每次买入的时候减个手续费就行
按照第三题的思路加入一个循环处理购买次数即可: 但是这样写的话会导致内存爆炸.JS好弱啊Orz
所以就要在以前的不用DP数组的版本去改造,还有就是压缩K的值,因为一次交易由买入和卖出构成,至少需要两天。所以说有效的限制 k 应该不超过 n/2
最后更新于