这个题和买股票的最佳时机一模一样,所以题目和示例就不再陈述,这篇主要说一下动态规划解决这个问题。前面我们使用暴力法和滑动窗口的方式解决了这个问题,但是最好的思路是动态规划。
这个题目很简单,但是对我们理解动态规划很有帮助,碰到最优问题,或者是结果数组存在某些联系的问题,我们最应该先想到动态规划,因为它的本质是:
- 求解最优结果,每次的最优结果通过状态转移方程不断计算得到。
- 借助辅助空间,将每次的结果记忆化,降低时间复杂度。
那我们就看一下这个题目如何使用动态规划,首先考虑用数组状态,定义状态转移方程,是否可以优化空间:
- 我们需要先选择一个最小的买入点,c=min(price[i],c)
- 我们需要得到最大的利润,一个买出点存在多个利润,但我们需要最大的,所以我们用数组dp[i]保存第 i 天的最大利润。
- 状态转移方程:就是思考如何用前一次的结果推导出现在的。那么第 i 天的利润是prices[i]-c,如果它小于dp[i-1],表示第i-1天的利润更大,那么第i天的利润就是dp[i-1]。所以dp[i]=max(dp[i]-c,dp[i-1])。
- 最后返回dp[i]即可,即到最后一天的最大利润。
我们先用示例看一下过程:示例:输入: [7,1,5,3,6,4] 输出: 5
那我们可以明显的看到dp[i]的结果,只和dp[i-1],c有关,那么尝试去优化dp。
因为dp[i-1]每次保存的都是最大值,所以那么我们可以用一个变量代替dp[i-1],我们定义为pro,pro=max(pro,dp[i]-c),这也是优化后的转移方程,那么这个代码就很简单:
int maxProfit(vector<int>& prices)
{
if(!(prices.empty()))
{
int c=prices[0];//定义初始买入点
int pro=INT_MIN;//初始利润最大值
for(int i=0;i<prices.size();i++)
{
c=min(c,prices[i]);
pro=max(pro,prices[i]-c);
}
return pro;
}
return 0;
}
其实写完代码,发现和滑动窗口的代码还挺像的,但是这两个思路还是有很大差异的,都是很重要的。
加油哦!💪。