C++ day50 买卖股票最佳时机

题目1:123 买卖股票的最佳时机Ⅲ

题目链接:买卖股票的最佳时机Ⅲ

对题目的理解

prices[i]表示股票在第i天的价格,最多可以完成两笔交易,不能同时进行多笔交易

可以买卖一次,两次,也可以不买卖

动态规划

动规五部曲

1)dp数组及下标i的含义

dp[i][0]  不操作(可有可无)股票的最大现金

dp[i][1]  第一次持有股票的最大现金

dp[i][2]  第一次不持有股票的最大现金

dp[i][3]  第二次持有股票的最大现金

dp[i][4]   第二次不持有股票的最大现金

不持有股票现金的状态一定比持有股票的现金多,第二次不持有一定包含第一次不持有的钱

最终求解: dp[prices.size()-1][4]

2)递推公式

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

dp[i][1] = dp[i-1][1]  前一天已经持有

dp[i][1] = dp[i-1][0]-prices[i]   第i天买入,前一天不操作

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

dp[i][2] = dp[i-1][2]  前一天不持有

dp[i][2] = dp[i-1][1]+prices[i]    第i天卖出 前一天持有

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

dp[i][3] = dp[i-1][3]  前一天已经持有

dp[i][3] = dp[i-1][2] -prices[i]  第i天买入,但是因为是第二次买入,所以应该是在第一次卖出的基础上减去第i天的股票价格

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

dp[i][4] = dp[i-1][4]  前一天不持有

dp[i][4] = dp[i-1][3] + prices[i]  第i天卖出,但是因为是第二次卖出,所以应该在第二次买入的基础上加上第i天的股票价格

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

3)dp数组初始化

从递推公式可以看出,i的状态由i-1的状态决定,所以初始化dp[0]

dp[0][0]=0

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

dp[0][2]=0(同一天买卖)

dp[0][3]=-prices[0](第二次又买入了)

dp[0][4]=0(第二次又卖出了)

4)遍历顺序

从递推公式可以看出,i的状态由i-1的状态决定,所以从小到大遍历

for(i=1;i 注意从1开始

5)打印dp数组

代码

class Solution {
public:
    int maxProfit(vector& prices) {
        //定义dp数组
        vector> dp(prices.size(),vector(5));
        //初始化dp数组
        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
  • 时间复杂度:O(n)
  • 空间复杂度:O(n × 5)

不使用dp[i][0]这个数组,直接将dp[i][0]相关的部分注释掉即可

代码

class Solution {
public:
    int maxProfit(vector& prices) {
        //定义dp数组
        vector> dp(prices.size(),vector(5));
        //初始化dp数组
      //  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

题目2:买卖股票的最佳时机Ⅳ

题目链接:买卖股票的最佳时机Ⅳ

对题目的理解

prices[i]是某支股票在第i天的价格,最多可以完成k笔交易,不能同时参与多笔交易

动规五部曲

1)dp数组及下标i的含义

dp[i][j]:第i天的状态为j(持有股票奇数,不持有股票偶数)所拥有的最大现金,j大于等于0,小于等于2k

最终求解:dp[prices.size()-1][2k]

2)递推公式

for(j=0;j<2k-1;j+=2)  //j控制第几次买卖

第j次持有  dp[i][j+1] = max(dp[i-1][j+1],dp[i][j]-prices[i]);

第j次不持有  dp[i][j+2] = max(dp[i-1][j+2],dp[i][j+1]+prices[i]);

3)dp数组初始化

根据递推公式,j为奇数,表示持有,for(int j=1;j<2k;j+=2)  dp[0][j]=-prices[0]

4)遍历顺序

根据递推公式,从小到大遍历

5)打印dp数组

代码

class Solution {
public:
    int maxProfit(int k, vector& prices) {
        //定义dp数组
        vector> dp(prices.size(),vector(2*k+1));
        //初始化dp数组
        for(int j=1;j<2*k;j+=2){//j为奇数下标时全为-prices[0],j是下标,应不超过2k+1
            dp[0][j]=-prices[0];
        } 
        //递推
        for(int i=1;i
  • 时间复杂度: O(n * k),其中 n 为 prices 的长度
  • 空间复杂度: O(n * k)

你可能感兴趣的:(c++,动态规划,开发语言)