今天是动态规划算法学习的第八天,也是买卖股票的一天。涉及到了使用多维数组来表示不同的状态,然后进行状态转移。
题目链接: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 - 力扣(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 - 力扣(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