动态规划:LC121.买卖股票的最佳时机

题目描述:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。 若是你最多只容许完成一笔交易(即买入和卖出一支股票一次),设计一个算法来计算你所能获取的最大利润。 注意:你不能在买入股票前卖出股票。java

思路:

动态规划的 5 个步骤:算法

一、设定状态

这道题实际上是一个典型的二维 dp 问题。「动态规划」用于多阶段最优化问题的求解。这里天数表明每一个阶段,即一天一天看,设置为第一维。为了消除后效性(前面的状态肯定下来之后不会由于后面状态而更改),将当天是否持股设置为第二维的状态。因而:数组

状态 dp[i][j] 表示:在下标为 i 的这一天,用户手上持股状态为 j 所得到的最大利润。优化

说明: j 只有 2 个值:0 表示不持股(特指卖出股票之后的不持股状态),1 表示持股。 「用户手上不持股」不表明用户必定在下标为 i 的这一天把股票抛售了;ui

二、思考状态转移方程
  • dp[i][0] 怎样转移?

dp[i - 1][0] :固然能够从昨天不持股转移过来,表示从昨天到今天什么都不操做,这一点是显然的;设计

dp[i - 1][1] + prices[i]:昨天持股,就在下标为 i 的这一天,我卖出了股票,状态由 1 变成了 0,此时卖出股票,所以加上这一天的股价。code

综上:dp[i][0] = max(dp[i - 1][0], dp[i - 1][1] + prices[i]);leetcode

  • dp[i][1] 怎样转移?

dp[i - 1][1] :昨天持股,今天什么都不操做,固然能够从昨天持股转移过来,这一点是显然的;it

-prices[i]:注意:状态 1 不能由状态 0 来,由于事实上,状态 0 特指:「卖出股票之后不持有股票的状态」,请注意这个状态和「没有进行过任何一次交易的不持有股票的状态」的区别。io

所以,-prices[i] 就表示,在下标为 i 的这一天,执行买入操做获得的收益。注意:由于题目只容许一次交易,所以不能加上 dp[i - 1][0]。

综上:dp[i][1] = max(dp[i - 1][1], -prices[i]);

三、考虑初始值

第 0 天不持股,显然 dp[0][0] = 0;

第 0 天持股,显然dp[0][1] = -prices[0]。

四、考虑输出

从状态转移方程能够看出,每一天的状态都考虑了以前的状态。在只发生一次交易的状况下,持有这支股票必定不能使咱们得到最大利润。所以输出是 dp[len - 1][0],不多是持股的状态 dp[len - 1][1],

做者:liweiwei1419 连接:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/solution/bao-li-mei-ju-dong-tai-gui-hua-chai-fen-si-xiang-b/

代码:

class Solution {
    public int maxProfit(int[] prices) {
        //定义状态:dp[i][j]--在第i天,用户持股状态为j时所得到的最大利润。  
        //状态关系:dp[i][0]=max(dp[i-1][0],dp[i-1][1]+price[i]);
        //          dp[i][1]=max(dp[i-1][1],-price[i]); ---j不能由0->1,因此只是-price[i]
        //初始值:dp[0][0]=0--不持股利润为0;dp[0][1]=-price[0]  
        
        //if(prices==null) return 0;   wrong!
        int len=prices.length;
        if(len<2) return 0;
        int[][] dp=new int[prices.length+1][2];
        dp[0][0]=0;
        dp[0][1]=-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],-prices[i]);
        }
        return dp[len-1][0];
    }
}
相关文章
相关标签/搜索