<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          小白學(xué)算法:買賣股票的最佳時機(jī)!

          共 1286字,需瀏覽 3分鐘

           ·

          2020-11-18 09:21

          作者 | 王磊

          來源 | Java中文社群(ID:javacn666)

          轉(zhuǎn)載請聯(lián)系授權(quán)(微信ID:GG_Stone)

          本文已收錄至 Github《小白學(xué)算法》系列:https://github.com/vipstone/algorith

          今天螞蟻集團(tuán)(支付寶)正式上市了,毫無疑問這一舉措又造就了一大批富豪,然而作為局外人的我們,也只有羨慕的份了。明明可以靠運氣吃飯,咱非得靠實力,你說虧不虧啊?

          但話又說回來,能進(jìn)螞蟻的人也都是牛人,那咱也趕緊提升一下技能吧,好為下一個“螞蟻”做足準(zhǔn)備。

          今天的這道題比較有意思,是關(guān)于「買賣股票」的,題目如下。

          題目描述

          給定一個數(shù)組,它的第 i 個元素是一支給定股票第 i 天的價格。如果你最多只允許完成一筆交易(即買入和賣出一支股票一次),設(shè)計一個算法來計算你所能獲取的最大利潤。

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

          示例 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。

          來源:LeetCode

          劍指 offer 64:https://leetcode-cn.com/problems/gu-piao-de-zui-da-li-run-lcof/submissions/難度:中

          leetcode 121:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock/難度:簡單

          解題思路

          根據(jù)題目的意思我們知道,我們只有一次交易的機(jī)會,也就是買一次再賣一次,但同時要保證收益最大化。那我們本能的直覺是在最低的價格買入,再在最高的價格賣出就好了,如下圖所示:


          但這有一個問題,就是我們要保證最高價格要在最低的價格之后,因為我們必須在購買了股票之后才能賣出,而不是相反的順序,這就讓問題變的復(fù)雜了。

          但此刻我們想到了一個最直接也是最笨的一個方法,那就是用暴力窮舉法,我們使用兩層循環(huán),依次在每個節(jié)點買入,然后再在之后的所有節(jié)點賣出,這樣來計算節(jié)點間的差值(收益),如果此差值大于當(dāng)前最高收益,就將此值設(shè)置為當(dāng)前最高收益,這樣循環(huán)完,我們就能獲得最大收益了。如下圖所示:


          方法一:暴力法

          有了上面的思路,接下來我們用代碼實現(xiàn)一下:

          class?Solution?{
          ????public?int?maxProfit(int[]?prices)?{
          ????????int?mp?=?0;?//?最高收益
          ????????for?(int?i?=?0;?i?????????????for?(int?j?=?i?+?1;?j?????????????????int?item?=?prices[j]?-?prices[i];
          ????????????????if?(item?>?mp)?mp?=?item;
          ????????????}
          ????????}
          ????????return?mp;
          ????}
          }

          可以看出代碼還是很簡單的,但別高興得太早,我們來看它在 leetcode 上的表現(xiàn):

          復(fù)雜度分析

          • 時間復(fù)雜度:O(n^2),循環(huán)運行 n(n-1)/2 次。
          • 空間復(fù)雜度:O(1),只使用了常數(shù)位的變量。

          真是一頓操作猛如虎,最終擊敗百分之五!如果用這種代碼去面試的話,估計只能回去等通知了。那有沒有更好的方法呢?答案是肯定的,繼續(xù)往下看。

          方法二:遍歷一次

          對于這道題我們其實可以使用一次循環(huán)來實現(xiàn),先來看下面的這張折線圖:


          從上面的圖片我們可以看出,我們在每個節(jié)點其實只會做兩件事(第一個節(jié)點除外,只能買入不能賣出),這兩件事分別是:買入或賣出。那么我們其實可以用一個循環(huán)來計算出最大的利潤,我們只需要依次對于每個節(jié)點做以下兩個判斷:

          • 判斷當(dāng)前節(jié)點是不是相對最低價,如果是,則將它設(shè)置為最低價(也就是買入);
          • 如果當(dāng)前節(jié)點不是最低價,那我們就將它賣出,然后計算賣出的收益(當(dāng)前節(jié)點減去相對最低價),如果賣出的收益大于目前的最高收益,則將此值設(shè)置為最高收益。

          這樣循環(huán)完成之后最高收益就出來了,實現(xiàn)代碼如下:

          class?Solution?{
          ????public?int?maxProfit(int?prices[])?{
          ????????if?(prices?==?null?||?prices.length?==?0)?return?0;
          ????????int?mp?=?0;?//?最高收益
          ????????int?min?=?prices[0];?//?最低價
          ????????for?(int?i?=?1;?i?????????????if?(prices[i]?????????????????//?設(shè)定相對最低價
          ????????????????min?=?prices[i];
          ????????????}?else?if?(mp?????????????????//?設(shè)定最高盈利
          ????????????????mp?=?prices[i]?-?min;
          ????????????}
          ????????}
          ????????return?mp;
          ????}
          }

          以上代碼在 leetcode 中的結(jié)果如下圖所示:

          復(fù)雜度分析

          • 時間復(fù)雜度:O(n),只需要遍歷一次。
          • 空間復(fù)雜度:O(1),只使用了常數(shù)個變量。

          從以上的執(zhí)行的結(jié)果可以看出,這段代碼還算是比較理想的,這樣面試官也會對你豎起大拇指了。

          總結(jié)

          本文我們計算了單次(一次買入和賣出)股票的最高收益,剛開始我們使用的是最簡單粗暴的暴力枚舉法,使用兩層循環(huán)依次相減來求出最高收益值,但這種方法的執(zhí)行效率太低。

          然后我們經(jīng)過觀察折線圖發(fā)現(xiàn),只需要一次循環(huán)也能找出最高的收益值。我們只需要在每個節(jié)點做兩個判斷,第一:判斷此節(jié)點是否為相對最小值,如果是,則記錄下來;如果不是,則計算此值和相對最小值是否為當(dāng)前最高收益,如果是,則記錄下來。那么循環(huán)一圈之后,我們就能得出最高的收益了,并且執(zhí)行的效率也很高。

          你學(xué)會了嗎?有不懂的地方或者更好的方法,歡迎評論區(qū)留言~

          —?【 THE END 】—
          本公眾號全部博文已整理成一個目錄,請在公眾號里回復(fù)「m」獲取!


          3T技術(shù)資源大放送!包括但不限于:Java、C/C++,Linux,Python,大數(shù)據(jù),人工智能等等。在公眾號內(nèi)回復(fù)「1024」,即可免費獲取!!





          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  麻豆三级片大全 | 噜一噜影院 | 91啪啪啪网站 | 久久肏逼 | 成人三级电影大香蕉 |