代码随想录算法训练营第三十五天| 121. 买卖股票的最佳时机,122.买卖股票的最佳时机II,123.买卖股票的最佳时机III

今天是动态规划算法学习的第八天,也是买卖股票的一天。涉及到了使用多维数组来表示不同的状态,然后进行状态转移。

121. 买卖股票的最佳时机

题目链接:121. 买卖股票的最佳时机 - 力扣(LeetCode)

这个题目是给出一个数组表示股票每天的价格,只能进行一次股票的买卖。求解所能获得的最大利润。我自己的做法是用前缀和,求每个数右边最大的数,然后求最大的差值。具体代码如下所示:

class Solution {
public:
    int maxProfit(vector& prices) {
        if(prices.size()==1) return 0;
        vector max_num(prices.size()+1);
        max_num[prices.size()-1]=0;
        for(int i=prices.size()-2;i>=0;i--)
        {
            max_num[i]=max(prices[i+1],max_num[i+1]);
        }
        int result=0;
        for(int i=0;iresult) result=max_num[i]-prices[i];
        }
        return result;

    }
};

接下来我将详细解释一下动态规划的做法。首先我们定义一个二维dp数组,dp[i][0]表示持有股票i所能获得的最大利润,dp[i][1]表示不持有股票i所能获得的最大利润。对于递推公式,dp[i][0]有两种状态可以推导,dp[i-1][0]和dp[i-1][1]-prices[i],dp[i-1][0]表示之前已经持有股票,现在依旧持有;0-prices[i]表示购买股票i。
 

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

同理,对于dp[i][1]也有两种状态转移方式,i-1时不持有股票i时要不持有股票,dp[i-1][1];或是i-1时持有股票i时卖出股票。

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

综上所示,递推公式有两个,如下所示:
 

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

对于初始化,dp[0][0]=-prices[0],dp[0][1]=0;

具体代码实现如下所示:
 

class Solution {
public:
    int maxProfit(vector& prices) {
        int dp[prices.size()+1][2];
        dp[0][0]=-prices[0];
        dp[0][1]=0;
        for(int i=1;i

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

题目链接:122. 买卖股票的最佳时机 II - 力扣(LeetCode)

这个题目取消了只能购买一次的限定条件,可以无限次的买入卖出。我自己是先用了贪心解决的。就是求解每个差值为正的相邻股票并相加即可得到最大利润。具体代码实现如下所示:
 

class Solution {
public:
    int maxProfit(vector& prices) {
        vector nums(prices.size(),0);
        int sum=0;
        for(int i=0;i0) sum+=nums[i];
        return sum;
    }
};

接下来是动态规划的解法,其实区别在于我们的递推公式。由于可以买卖无数次,那么d[i][0]的更新方式应该改变。

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])

其他的还是没有变化,具体代码实现如下所示:

class Solution {
public:
    int maxProfit(vector& prices) {
        int dp[prices.size()+1][2];
        dp[0][0]=-prices[0];
        dp[0][1]=0;
        for(int i=1;i

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

题目链接:123. 买卖股票的最佳时机 III - 力扣(LeetCode)

这个题目是限定只能对股票进行两次买卖操作,我们需要对dp数组进行重新定义。dp[i][0]表示没有操作,dp[i][1]表示第一次持有股票,dp[i][2]表示第一次不持有股票,dp[i][3]表示第二次持有股票,dp[i][4]表示第二次不持有股票。递推公式如下所示

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]);

最后直接获取dp[prices.size() - 1][4],即是最大利润。具体代码实现如下所示:
 

class Solution {
public:
    int maxProfit(vector& prices) {
        if(prices.size()==0) return 0;
        int dp[prices.size()+1][5];
        dp[0][0]=0;
        dp[0][1]=-prices[0];
        dp[0][2]=0;
        dp[0][3]=-prices[0];
        dp[0][4]=0;
        for(int i=1;i

你可能感兴趣的:(算法打卡,算法,数据结构,动态规划,贪心算法,leetcode)