前缀最值
什么?动态规划还能计算股票的最大利润?学好动态规划就能炒股了吗,那我倒要看看是怎么回事。
题干
给定一个数组prices,prices[i]表示股票i天的价格,只能在某天买入并在未来某一天卖出,计算你所能获得的最大利润。
题目分析
emm,需要怎么说吗,像这种只要答案不需要给出过程的题目,八九不离十,就是动态规划了。我太懂了。。
动态规划题目的解题步骤:
- 定义最优状态数组
dp = []
, - 确定状态转移方程
dp[i]=xxxx
- 递推出最终答案
result
解题的根本思路就是:从下标0开始找到每个下标为止(不包括当前下标)的最小值,先找出每个下标的最小值。接着找每个最小值右边的最大值。两者相减得到的就是最大利润。取最大值就是我们要的答案
解题步骤
-
定以最佳状态,
dp[]
,dp[i]
表示xx表为i及之前的数值的最小值 -
计算前缀最小值
如何计算?
如果只有1位,前面没有数,那么它就是最小值,即:
dp[0]=prices[0]
如果是有2位,前面有1位数,那么最小值就是
当前值
比较前一位为止的最小值,即dp[1]=min(dp[1-1],prices[1])
如果是有3位,那么最小值也是
当前值
比较前一位为止的最小值
,即dp[2]=min(dp[2-1],prices[2])
-
定义一个结果最大值,再遍历一遍价格,用
当前价格
减去当前下标前的最小值
,取遍历结果的最大值就是我们要的答案
代码实现(js)
function sharesBisnes(){
// 股票的最佳买卖时机
/* 前缀最值
给定一个数组prices,prices[i]表示股票i天的价格,只能在某天买入并在未来某一天卖出,计算你所能获得的最大利润
*/
let prices =[7,1,5,3,6,4] // 结果为:5 ;i:1和4
// 算出前面i天的最低价,记为dp[i]
dp = []
prices.forEach((item,i)=>{
if(i == 0){
dp[i] = item
}else{
dp[i] = min(dp[i-1],item)
}
})
// 用第i天前最低价减去第i天价格,同时记录最大值,就得到最大利润了
ans = 0;
prices.forEach((item,i)=>{
ans = max(item-dp[i],ans)
})
document.write("最大利润为"+ans)
}
function max(a,b){
return a > b ? a : b
}
总结
求前缀最值其实比较简单,这篇文废话也相对比较多。本文是包括了计算前缀最值,但不是直接用前缀最值来解答。
前缀最值就是求到i为止的最大值或者最小值,用遍历的方式同样可以实。但是用动态规划的思想,前一位数已经算出最小值了,那么当前这位数的最值,要么就是前一位的最值要么就是本身咯,这样往后推,不管数组多长,我们的时间复杂度一直是一个常数。