代碼隨想錄算法訓(xùn)練營打卡Day50 | LeetCode123 買賣股票的最佳時(shí)機(jī)III豺妓、LeetCode188 買賣股票的最佳時(shí)機(jī)IV

摘要

  • 只買賣一次股票,和不限制次數(shù)地買賣股票彭谁,只是在遞推公式上有差別马靠。而且,這兩種情況都不需要記錄完成買賣的次數(shù)俊戳。

  • 指定了至多買k次股票渐北,這就暗含著每天的狀態(tài)信息要有買賣股票的次數(shù)歧蒋。

LeetCode123 買賣股票的最佳時(shí)機(jī)III

123. 買賣股票的最佳時(shí)機(jī) III - 力扣(Leetcode)

  • 這題和前面兩題買賣股票(代碼隨想錄算法訓(xùn)練營打卡Day49)的區(qū)別還是買賣股票的次數(shù)贸宏。而這題的特點(diǎn)就是我們要控制至多買2次股票锦聊。

    • 至多買一次股票,和不限制次數(shù)地買賣股票箩绍,只是在遞推公式上有差別孔庭。而且,這兩種問題都不需要記錄完成買賣的次數(shù)材蛛。
    • 但是圆到,至多買2次股票,這就暗含著每天的狀態(tài)信息要有買賣股票的次數(shù)卑吭。所以芽淡,這道題和前兩題的除了在遞推公式上有差別,在dp數(shù)組的定義上也有差別豆赏。
  • 確定dp數(shù)組及數(shù)組下標(biāo)的含義:

    • dp[i][j]表示的是第i天買賣股票可能獲得的最大利潤(rùn)挣菲,
    • j == 0表示在第i天或第i天之前第一次買入了股票
    • j == 1表示在第i天或第i天之前第一次賣出了股票
    • j == 2表示在第i天或第i天之前第二次買入了股票
    • j == 3表示在第i天或第i天之前第二次賣出了股票
  • 確定狀態(tài)轉(zhuǎn)移方程,假設(shè)一開始持有的金額為0

    • 對(duì)于第0天河绽,

      • 對(duì)于第一次買賣股票己单,如果買入了股票,只可能是在第0天時(shí)買入股票耙饰,所以dp[0][0] = 0 - prices[0]纹笼;如果賣出了股票,只能是第0天買入后再賣出苟跪,金額不變廷痘,dp[0][1] = 0蔓涧。

      • 對(duì)于第二次買賣股票,也同理笋额,如果買入了股票元暴,只可能是在第0天時(shí)買入股票,所以dp[0][2] = 0 - prices[0]兄猩;如果賣出了股票茉盏,只能是第0天買入后再賣出,金額不變枢冤,dp[0][3] = 0鸠姨。

    • 對(duì)于第i天,先看第一次買賣

      • 如果買入了股票淹真,說明在第i天或之前的某一天第一次買入了股票讶迁。
        • 如果是在第i天買入了股票,至少第i-1天時(shí)是未持有股票的核蘸,根據(jù)dp數(shù)組的定義巍糯,第i-1天持有的金額是dp[i-1][1],那么第i天時(shí)持有的金額為dp[i][0] = dp[i-1][1] - prices[i]客扎;
        • 如果在之前的某一天買入了股票祟峦,現(xiàn)在還應(yīng)該繼續(xù)持有股票,所以 dp[i][0] = dp[i - 1][0]虐唠,保持著持有之前買入的股票的狀態(tài)搀愧。
      • 如果賣出了股票惰聂,說明在第i天或之前的某一天第一次賣出了股票疆偿。
        • 如果是在第i天買入了股票,至少第i-1天時(shí)是持有股票的搓幌,根據(jù)dp數(shù)組的定義杆故,第i-1天持有的金額是dp[i-1][0],那么第i天時(shí)持有的金額為dp[i][1] = dp[i - 1][0] + prices[i]溉愁;
        • 如果在之前的某一天賣出了股票处铛,第i天還不應(yīng)該買入股票,所以拐揭,保持之前的狀態(tài)即可 dp[i][1] = dp[i - 1][1]
    • 再看第二次買賣撤蟆,因?yàn)轭}目明確說了不能同時(shí)參與多筆交易,所以第二次買賣必須在第一次買賣完成之后進(jìn)行堂污,所以第二次買入的狀態(tài)是由第一次買賣完成的狀態(tài)(即第一次賣出股票dp[i - 1][1])轉(zhuǎn)移來的家肯。

      • 如果買入了股票,在第i天或之前的某一天第二次買入了股票盟猖。

        • 如果是在第i天買入了股票讨衣,至少第i-1天時(shí)是未持有股票的换棚,可以假設(shè)第i-1天時(shí)已經(jīng)完成了第一次買賣,根據(jù)dp數(shù)組的定義反镇,第i-1天持有的金額是dp[i-1][1]固蚤,那么第i天時(shí)持有的金額為dp[i][0] = dp[i-1][1] - prices[i]
        • 如果在之前的某一天買入了股票歹茶,現(xiàn)在還應(yīng)該繼續(xù)持有股票夕玩,所以 dp[i][2] = dp[i - 1][2],保持著持有之前買入的股票的狀態(tài)惊豺。
      • 如果賣出了股票风秤,在第i天或之前的某一天第二次賣出了股票。

        • 如果是在第i天買入了股票扮叨,至少第i-1天時(shí)是持有股票的缤弦,根據(jù)dp數(shù)組的定義,第i-1天持有的金額是dp[i-1][0]彻磁,那么第i天時(shí)持有的金額為dp[i][1] = dp[i - 1][0] + prices[i]碍沐;
        • 如果在之前的某一天賣出了股票,第i天還不應(yīng)該買入股票衷蜓,所以累提,保持之前的狀態(tài)即可 dp[i][1] = dp[i - 1][1]
    • 狀態(tài)轉(zhuǎn)移方程
      dp[i][0] = max(dp[i - 1][0], 0 - prices[i]) \\ dp[i][1] = max(dp[i - 1][1], dp[i - 1][0] + prices[i]) \\ dp[i][2] = max(dp[i - 1][0], dp[i - 1][1] - prices[i]) \\ dp[i][3] = max(dp[i - 1][1], dp[i - 1][2] + prices[i]) \\

  • 按推導(dǎo)出的第0天的狀態(tài)來初始化dp數(shù)組。

  • 遍歷順序磁浇,dp[i][j]的更新依賴于dp[i-1][j]斋陪,所以i應(yīng)該從小到大遍歷,第一次和第二次買賣股票有先后順序置吓,j應(yīng)該從小到大更新无虚。

題解代碼如下

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

        for (int i = 1; i < prices.size(); i++) {
            dp[i][0] = max(dp[i - 1][0], 0 - prices[i]);
            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]);
        }

        return dp[prices.size() - 1].back();
    }
};

LeetCode188 買賣股票的最佳時(shí)機(jī)IV

188. 買賣股票的最佳時(shí)機(jī) IV - 力扣(Leetcode)

  • 這題的解法其實(shí)就是動(dòng)態(tài)地控制“買賣股票的最佳時(shí)機(jī)III”的中的最多買賣次數(shù)。最多買賣次數(shù)從兩次變成了k次衍锚,實(shí)際上就是添加一個(gè)循環(huán)來表示從第j - 1次買賣到第j次買賣的狀態(tài)轉(zhuǎn)移友题。

  • 確定dp數(shù)組及數(shù)組下標(biāo)的含義:

    • dp[i][j]表示的是第i天買賣股票可能獲得的最大利潤(rùn),j0或偶數(shù)時(shí)表示第j%2+1次持有股票戴质,j為奇數(shù)時(shí)表示第j%2+1次賣出股票度宦。
  • 確定狀態(tài)轉(zhuǎn)移方程,關(guān)鍵在于每次買賣之間的狀態(tài)轉(zhuǎn)移

    • 0天的初始化要注意告匠,不能只初始化第一次買賣的狀態(tài)戈抄,每次買賣都要初始化,j \in [0, 2k) \wedge j \% 2 == 0

    dp[i][j] = 0 - prices[0] \\ dp[i][j+1] = 0

    • 對(duì)于第i天后专,如果是第一次買賣划鸽,假設(shè)一開始持有的金額為0

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

    • 對(duì)于第i天,如果不是第一次買賣行贪,假設(shè)當(dāng)前是第j%2+1次買賣漾稀,則第i天第j%2+1次買賣的買賣是由已經(jīng)完成了j-1次買賣的狀態(tài)轉(zhuǎn)移來的

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

  • 初始狀態(tài)就是第0天的狀態(tài)模闲,按第0天的狀態(tài)初始化dp數(shù)組。

  • 遍歷順序的道理和上一題相同崭捍,i從小到大遍歷尸折,j也從小到大遍歷。

題解代碼如下

class Solution {
public:
    int maxProfit(int k, vector<int>& prices) {
        vector<vector<int>> dp(prices.size(), vector<int>(2 * k, 0));
        for (int j = 0; j < 2 * k; j += 2) {
            dp[0][j] = 0 - prices[0];
        }

        for (int i = 1; i < prices.size(); i++) {
            for (int j = 0; j < 2 * k; j += 2) {
                // 判斷一下是不是第一次買賣股票殷蛇,防止數(shù)組下標(biāo)越界
                if (j == 0) dp[i][j] = max(dp[i - 1][j], 0 - prices[i]);
                else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - 1] - prices[i]);
                dp[i][j + 1] = max(dp[i - 1][j + 1], dp[i - 1][j] + prices[i]);
            }
        }

        return dp[prices.size() - 1][2 * k - 1];
    }
};
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末实夹,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子粒梦,更是在濱河造成了極大的恐慌亮航,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匀们,死亡現(xiàn)場(chǎng)離奇詭異缴淋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)泄朴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門重抖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人祖灰,你說我怎么就攤上這事钟沛。” “怎么了局扶?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵恨统,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我三妈,道長(zhǎng)畜埋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任沈跨,我火速辦了婚禮由捎,結(jié)果婚禮上兔综,老公的妹妹穿的比我還像新娘饿凛。我一直安慰自己,他們只是感情好软驰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布涧窒。 她就那樣靜靜地躺著,像睡著了一般锭亏。 火紅的嫁衣襯著肌膚如雪纠吴。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天慧瘤,我揣著相機(jī)與錄音戴已,去河邊找鬼固该。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糖儡,可吹牛的內(nèi)容都是我干的伐坏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼握联,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼桦沉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起金闽,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤纯露,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后代芜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體埠褪,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年挤庇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了组橄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡罚随,死狀恐怖玉工,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情淘菩,我是刑警寧澤遵班,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站潮改,受9級(jí)特大地震影響狭郑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜汇在,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一翰萨、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧糕殉,春花似錦亩鬼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至羡洁,卻和暖如春玷过,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國打工辛蚊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留粤蝎,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓袋马,卻偏偏與公主長(zhǎng)得像诽里,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子飞蛹,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容