代碼隨想錄算法訓練營|第五十三天|309 最佳买卖股票时机含冷冻期、714 买卖股票的最佳时机含手续费、股票总结。刷题心得(c++)

目录

讀題

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

自己看到题目的第一想法

看完代码随想录之后的想法

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

自己看到题目的第一想法

看完代码随想录之后的想法

309 最佳买卖股票时机含冷冻期 - 實作

思路

Code

714 买卖股票的最佳时机含手续费 - 實作

思路

Code

股票問題總結

總結

自己实现过程中遇到哪些困难

今日收获,记录一下自己的学习时长

相關資料

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

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

股票总结


讀題

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

自己看到题目的第一想法

我在思考這個不就是不操作加入到裡面,原本不操作只是為了方便操作,現在則是要考慮進去,如果考慮進去的話,只要下標定義清楚

實際做了之後,發現下標的定義定義為三個狀態

但是遞推公式很難推出來,想法很不清晰。

看完代码随想录之后的想法

原來是我的下標定義就錯了,這步錯後面推導就會出現問題

把不持有的兩個狀態進行拆分

已經賣出且過了冷凍期以及賣出股票

在加上第四個冷凍期,冷凍期一定是賣出的後一天

看完之後才比較清晰

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

自己看到题目的第一想法

這只是買賣股票II在sell時多加一個減去手續費的過程,其餘部分基本相同。

看完代码随想录之后的想法

看完之後真的就是跟之前一樣,只在再總結股票問題的部分講的很清晰

309 最佳买卖股票时机含冷冻期 - 實作

思路

  1. 定義DP數組以及下標的含意

    分為四種狀況

    dp[i][0]: 持有股票

    dp[i][1]: 保持賣出股票(已過冷凍期)

    dp[i][2]: 賣出股票

    dp[i][3]: 冷凍期

  2. 遞推公式

    dp[i][0] 會有兩種角度三種情況

    • 保持持有 dp[i - 1][0]
    • 買入股票,買入股票有兩個時機,一個是冷凍期後買入,一個是保持賣出股票買入
      • 冷凍期

        dp[i - 1][3] - prices[i]

      • 保持賣出股票

        dp[i - 1][1] - prices[i]

    dp[i][1] 保持賣出則是也有兩種狀況

    • 上一次保持持有以及過了冷凍期
      • 保持持有

        dp[i - 1][1]

      • 過了冷凍期

        dp[i - 1][3]

    dp[i][2] 賣出股票就一種狀態 dp[i - 1][0] + prices[i]

    dp[i][3] 冷凍期也只有一個狀態就是賣出後 dp[i - 1][2]

  3. 根據遞推公式、題意以及定義,確定DP數組如何初始化

    dp[0][0] = -prices[0] 就是一開始的現金

    dp[0][1]、dp[0][3] 本身是一個非法狀態,但是套入的推公式,根據需要初始化為0

    dp[0][2] 賣出後正負相抵,初始化為0

  4. 確定遍歷順序

    是透過前面的狀況推導出後面的狀況,所以是由前往後遍歷

Code

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

714 买卖股票的最佳时机含手续费 - 實作

思路

  1. 定義DP數組以及下標的含意

    分為兩種狀況

    dp[i][0] 第i天持有股票的現金

    dp[i][1] 第i天不持有股票所得的現金

  2. 遞推公式

    dp[i][0]

    分兩種狀況

    • 第i - 1天持有股票的狀況 dp[i - 1][0]
    • 第i天持有股票的狀況,那就必須把目前的股票賣出買入新的股票,也就是dp[i - 1][1] -price[i],dp[i - 1] 代表前一天所得到的利潤

    我們要瞭解到dp[i][0] 主要是比較昨天持有比較值得還是今天持有該股票會比較值得

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

    也是分兩種狀況

    • 第i - 1天不持有股票所可以得到的最大金額
    • 第i天不持有股票所可以得到的最大金額

    dp[i][1] 可以思考為昨天之前賣掉股票會比較多錢還是今天賣股票會比較多錢

    最後再減去手續費

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

  3. 根據遞推公式、題意以及定義,確定DP數組如何初始化

    dp[0][0] 代表第一天持有股票 所以是-price[0]

    dp[0][1] 代表第一天還沒有賣出股票所以是 0

  4. 確定遍歷順序

    是透過前面的狀況推導出後面的狀況,所以是由前往後遍歷

Code

class Solution {
public:
    int maxProfit(vector<int>& prices, int fee) {
        vector<vector<int>> dp (prices.size(), vector<int>(2));
        dp[0][0] = -prices[0];
        dp[0][1] = 0;
        for(int i = 1; i < prices.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[prices.size() - 1][1];      
    }
};

股票問題總結

  • 單一股票買賣一次求最大数值,主要就是定義上持有股票的現金以及不持有的部分進行初步的劃分

  • 單一股票買賣多次求最大数值,主要就是定義上持有股票的現金以及不持有的部分進行初步的劃分

    • 动态规划:122.买卖股票的最佳时机II

    • 在遞推公式上就是在買入的時機會出現差異,變成是說上一次獲得的現金,減去當下的股票金額,哪個優

      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]);
      
  • 單一股票只能買賣特定次数

    • 动态规划:123.买卖股票的最佳时机III动态规划:188.买卖股票的最佳时机IV

    • 主要體現在下標上面就會有差異,分為沒有操作、買入股票、賣出股票這三個部分

    • 因為每次的買賣都一定是2 * k 次(買入、賣出),所以在的推公式上其實就是將買賣次数進行抽象化處理

      for(int j = 1; j < 2 * k + 1; j++) {
          if(j % 2 == 1) dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
          else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] + prices[i]);
      }
      
  • 單一股票只能買賣包含冷凍期

    • 动态规划:309.最佳买卖股票时机含冷冻期

    • 主要體現在定義上會有所差別,需要將賣出的狀態分為,保持賣出以及賣出,這樣使得冷凍期的數值有所依歸

    • 遞推公式如下

      dp[i][0] = max(dp[i - 1][0], max(dp[i - 1][3]- prices[i], dp[i - 1][1]- prices[i]));
      dp[i][1] = max(dp[i - 1][1], dp[i - 1][3]);
      dp[i][2] = dp[i - 1][0] + prices[i];
      dp[i][3] = dp[i - 1][2];
      
  • 單一股票多次買賣包含手續費

總結

自己实现过程中遇到哪些困难

困難點主要是狀態的拆分,買賣股票都有兩種狀態,買入、持續買入、賣出以及持續賣出,在冷凍的題目中如果沒有釐清這點就會出現很大的問題。

今日收获,记录一下自己的学习时长

主要學了1hr左右,題目比較少

主要是統整買賣股票的問題,以及了解冷凍期的思路

相關資料

● 今日学习的文章链接和视频链接

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

视频讲解:动态规划来决定最佳时机,这次有冷冻期!| LeetCode:309.买卖股票的最佳时机含冷冻期_哔哩哔哩_bilibili

https://programmercarl.com/0309.最佳买卖股票时机含冷冻期.html

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

视频讲解:动态规划来决定最佳时机,这次含手续费!| LeetCode:714.买卖股票的最佳时机含手续费_哔哩哔哩_bilibili

https://programmercarl.com/0714.买卖股票的最佳时机含手续费(动态规划).html

股票总结

https://programmercarl.com/动态规划-股票问题总结篇.html

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值