JS leetcode 買賣股票的最佳時機 題解分析,我離職了。


壹 ❀ 引

昨天下班后,還是找經理提出了辭職,沒有猶豫的裸辭,今天與人事的對話不小心被后台的同事聽到,一下在公司傳開了,下午我與同事們多人對線,被他們的消息轟炸....沒錯,我真的要走了。

因為什么原因呢?公司技術框架過於落后(angularjs1.6,不允許使用ES6等),很長時間我都很焦慮,擔心自己再待下去是否會被這個行業淘汰,在過去的時間也學了一些東西,但都沒法在工作中實踐,以及待遇等等問題縈繞於心,才出此決策。

在與獵頭的溝通中對方也是建議我先待着看看,不推薦裸辭,畢竟疫情影響行情不容樂觀。我說如果當下處境良好我定會觀望,只是深處溫室之中越久,自己反而越害怕離職,涅槃重生還需經歷烈火考驗,比起騎驢找馬,我還是更擅長破釜沉舟一點,祝自己好運。

還有一個月的工作交接期,順便復盤自己的工作經歷,還要復習,刷題,學習vue等等,壓力巨大。不過既然是自己的決定,那就努力做到最好就好了。當然,后續面試我也會不斷更新相關面試經歷,多總結多積累,總沒壞處。

好了,說了這么多,來看看今天的題目吧,題目來自121. 買賣股票的最佳時機,題目描述如下:

給定一個數組,它的第 i 個元素是一支給定股票第 i 天的價格。

如果你最多只允許完成一筆交易(即買入和賣出一支股票一次),設計一個算法來計算你所能獲取的最大利潤。

注意:你不能在買入股票前賣出股票。

示例 1:

輸入: [7,1,5,3,6,4]
輸出: 5

解釋: 在第 2 天(股票價格 = 1)的時候買入,在第 5 天(股票價格 = 6)的時候賣出,最大利潤 = 6-1 = 5 。
注意利潤不能是 7-1 = 6, 因為賣出價格需要大於買入價格;同時,你不能在買入前賣出股票。
示例 2:

輸入: [7,6,4,3,1]
輸出: 0

解釋: 在這種情況下, 沒有交易完成, 所以最大利潤為 0。

讓我們簡單分析題目,嘗試解決它。

貳 ❀ 題解分析

其實當我看到[7,1,5,3,6,4]的例子,我第一反應也是為啥不是7-1=6,其實在題目的注意已經說明,我們在賣出股票時,必須得先買入,想要賺的多,一定是在歷史最低價買入,在歷史最高價賣出。注意,這個歷史最低並不是數組中最小值,比如[3,5,1,2]這個例子,雖然我們在1買入最低,但后面價格只有2,利潤反而不如3買入后5賣出。

我們需要理清的一點是,比如在第i天賣出,那么一定是在i-1天中最小的價格買入,因為得先買才能后賣,所以最笨的做法就是使用雙循環,用嘗試算出每一個i天與之前(i-1,i-2...)的差價,再找出其中最大的一個值即可,比如:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
    // 因為如果沒有利潤就是0,這里初始化
    let maxProfit = 0;
    for (let i = 0; i < prices.length; i++) {
        // 注意,這里的j從i+1開始
        for (j = i + 1; j < prices.length; j++) {
            let profit = prices[j] - prices[i];
            // 不斷用當前利潤和歷史最大利潤比較,如果更大就替換maxProfit
            if (profit > maxProfit) {
                maxProfit = profit;
            };
        };
    };
    return maxProfit;
};

很簡單也非常好懂,但是我們也清楚,這個耗時太久,只要價格數據越大,我們查詢代價就越大。那么有沒有更好的做法呢?當然有。

其實找到最大利潤,其實無非就是找到歷史最低價格,但事實上我們不知道哪個是最低價,沒關系,我們可以先假設第一天是最低,遍歷數組的同時,讓當前價格與歷史最低比較,如果更低,那自然要更新歷史最低價了。

更新了最低價之后呢?當然是用當前價格減去歷史最低價求出利潤,並與歷史比較,始終記錄較大的利潤即可,直到遍歷結束,返回最終的價格不就是最大的利潤了,比如:

/**
 * @param {number[]} prices
 * @return {number}
 */
var maxProfit = function (prices) {
    let maxProfit = 0,
        // 假設0位價格為歷史最低
        minPrice = prices[0];
    // i從1開始
    for (let i = 1; i < prices.length; i++) {
        // 如果后續價格比歷史更低,更新最低價
        minPrice = Math.min(minPrice, prices[i]);
        // 計算利潤,找出最大利潤
        maxProfit = Math.max(maxProfit, prices[i] - minPrice);
    };
    return maxProfit;
};

我們來以[7,6,4,3,1]這個例子來看,由於價格越來越低,最低價格也一直隨便遍歷變化,導致利潤計算始終為0,而對於第一個例子,一旦鎖定了一個歷史低價,后續要做的就是不斷與之后的價格比較,從中找到最大利潤。

這個思路也叫動態規划,雖然我現在也不是很理解- - ,看后續做題能否積累,那么本文就到這里就結束了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM