算法系列——动态规划5

搞定股票问题,主要在于有无股票时的状态分析,分析来当前状来自哪个状态,在下面的五个题中都有详细的对应状态的分析

121. 买卖股票的最佳时机

class Solution {

public:

    int maxProfit(vector<int>& prices) {

        /*最大利润dp[i][2],下标i应该代表的是第i天,第i天两个状态:

        有股票手里的钱数,没有股票手里的钱数

        

        dp数组:有股份或者没股份手里的钱

        0今天没股份:昨天没股份,今天卖出了股份

        1今天有股份:昨天有股份,今天刚买的股份(第一次买)        

        

        */

        int m=prices.size();

        vector<vector<int>>dp(m,vector<int>(2));

        dp[0][0]=0;

        dp[0][1]=-prices[0];

        for(int i=1;i<dp.size();i++){

            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);

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

        }

        return dp[m-1][0];

    }

};

122. 买卖股票的最佳时机 II

class Solution {

public:

    int maxProfit(vector<int>& prices) {

        /*最大手里的钱数dp[i][2],下标i代表的是第i天,第i天两个状态:

        有股票手里的最大钱数,没股票手里的最大钱数

        dp数组:有股票手里的钱或没股票手里的钱

        0今天没股份的钱:昨天没股份,今天卖了股份

        1今天有股份的钱:昨天有股份,今天买了新的股份(昨天的股份已卖)

        dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);

        dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);

        */

        int m=prices.size();

        vector<vector<int>>dp(m,vector<int>(2));

        dp[0][0]=0;

        dp[0][1]=-prices[0];

        for(int i=1;i<dp.size();i++){

            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);

            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);

        }

        return dp[m-1][0];

    }

};

123. 买卖股票的最佳时机 III

class Solution {

public:

/*

    因为可以有两次交易,所以就有5个状态0,1,2,3,4分别代表

    0.啥也不做:继承昨天的状态dp[i][0]=dp[i-1][0];

    1.第一次有股:昨天有股,今天买dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);

    2.第一次无股:昨天第一次无股,今天卖昨天的第一次股,dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i]);

    3.第二次有股:昨天有股(第二次股),第一次的股被卖出今天买dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i]);

    4.第二次无股份:昨天第二次无股,今天卖昨天的第二次股dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i]);

*/

    int maxProfit(vector<int>& prices) {

        if(prices.size()==0return 0;

        int m=prices.size();

        vector<vector<int>>dp(m,vector<int>(5,0));

        dp[0][1]=-prices[0];

        dp[0][3]=-prices[0];

        for(int i=1;i<=m-1;i++){

            dp[i][0]=dp[i-1][0];

            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]);

            dp[i][2]=max(dp[i-1][2],dp[i-1][1]+prices[i]);

            dp[i][3]=max(dp[i-1][3],dp[i-1][2]-prices[i]);

            dp[i][4]=max(dp[i-1][4],dp[i-1][3]+prices[i]);

        }

        return dp[m-1][4];

   }

};

309. 最佳买卖股票时机含冷冻期

class Solution {

public:

    int maxProfit(vector<int>& prices) {

        /*

        dp[i][2]数组:第i天有股份或者没股份手里的最大收益

        dp[i][0]:有股份的最大收益:来自于昨天有股份,今天买入股份(今天能买证明他没股份不在冷冻期)

        dp[i][1]:没股份 在冷冻期的最大收益:来自与我把昨天的股份给卖了

        dp[i][2]:没股份 不在冷冻期的最大收益:来自于昨天没股份在冷冻期,没股份不在冷冻期

        dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]);

        dp[i][1]=dp[i-1][0]+prices[i];

        dp[i][2]=max(dp[i-1][1],dp[i-1][2]);

        

        */

        int m=prices.size();

        if(m==1return 0;

        vector<vector<int>>dp(m,vector<int>(3));

        dp[0][0]=-prices[0];

        dp[0][1]=0;

        dp[0][2]=0;

        for(int i=1;i<dp.size();i++){

            dp[i][0]=max(dp[i-1][0],dp[i-1][2]-prices[i]);

            dp[i][1]=dp[i-1][0]+prices[i];

            dp[i][2]=max(dp[i-1][1],dp[i-1][2]);

        }

        return max(dp[m-1][1],dp[m-1][2]);

    }

};

714. 买卖股票的最佳时机含手续费

class Solution {

public:

    int maxProfit(vector<int>& pricesint fee) {

        /*dp[i][2]数组:第i天有无股票的最大收益

        0无股票的最大收益:昨天无股票,今天卖股票

        1有股票的最大收益:昨天有股票,今天买股票

        规定手续费在买入的时候交

        dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);

        dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]-fee);

        */

        int m=prices.size();

        vector<vector<int>>dp(m,vector<int>(2));

        dp[0][0]=0;

        dp[0][1]=-prices[0]-fee;

        for(int i=1;i<dp.size();i++){

            dp[i][0]=max(dp[i-1][0],dp[i-1][1]+prices[i]);

            dp[i][1]=max(dp[i-1][1],dp[i-1][0]-prices[i]-fee);

        }

        return dp[m-1][0];

    }

};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值