<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é)算法:買賣股票的最佳時(shí)機(jī)!

          共 1045字,需瀏覽 3分鐘

           ·

          2020-11-20 21:12

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

          題目描述

          給定一個(gè)數(shù)組,它的第 i 個(gè)元素是一支給定股票第 i 天的價(jià)格。如果你最多只允許完成一筆交易(即買入和賣出一支股票一次),設(shè)計(jì)一個(gè)算法來(lái)計(jì)算你所能獲取的最大利潤(rùn)。
          注意:你不能在買入股票前賣出股票。
          示例 1:
          輸入: [7,1,5,3,6,4]
          輸出: 5
          解釋: 在第 2 天(股票價(jià)格 = 1)的時(shí)候買入,在第 5 天(股票價(jià)格 = 6)的時(shí)候賣出,最大利潤(rùn) = 6-1 = 5 。? ? 注意利潤(rùn)不能是 7-1 = 6, 因?yàn)橘u出價(jià)格需要大于買入價(jià)格;同時(shí),你不能在買入前賣出股票。
          示例 2:
          輸入: [7,6,4,3,1]
          輸出: 0
          解釋: 在這種情況下, 沒(méi)有交易完成, 所以最大利潤(rùn)為 0。
          來(lái)源: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/難度:簡(jiǎn)單

          解題思路

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

          但這有一個(gè)問(wèn)題,就是我們要保證最高價(jià)格要在最低的價(jià)格之后,因?yàn)槲覀儽仨氃谫?gòu)買了股票之后才能賣出,而不是相反的順序,這就讓問(wèn)題變的復(fù)雜了

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

          方法一:暴力法

          有了上面的思路,接下來(lái)我們用代碼實(shí)現(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;
          ????}
          }

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

          復(fù)雜度分析

          • 時(shí)間復(fù)雜度:O(n^2),循環(huán)運(yùn)行 n(n-1)/2 次。
          • 空間復(fù)雜度:O(1),只使用了常數(shù)位的變量。
          真是一頓操作猛如虎,最終擊敗百分之五!如果用這種代碼去面試的話,估計(jì)只能回去等通知了。那有沒(méi)有更好的方法呢?答案是肯定的,繼續(xù)往下看。

          方法二:遍歷一次

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

          從上面的圖片我們可以看出,我們在每個(gè)節(jié)點(diǎn)其實(shí)只會(huì)做兩件事(第一個(gè)節(jié)點(diǎn)除外,只能買入不能賣出),這兩件事分別是:買入或賣出。那么我們其實(shí)可以用一個(gè)循環(huán)來(lái)計(jì)算出最大的利潤(rùn),我們只需要依次對(duì)于每個(gè)節(jié)點(diǎn)做以下兩個(gè)判斷:
          • 判斷當(dāng)前節(jié)點(diǎn)是不是相對(duì)最低價(jià),如果是,則將它設(shè)置為最低價(jià)(也就是買入);
          • 如果當(dāng)前節(jié)點(diǎn)不是最低價(jià),那我們就將它賣出,然后計(jì)算賣出的收益(當(dāng)前節(jié)點(diǎn)減去相對(duì)最低價(jià)),如果賣出的收益大于目前的最高收益,則將此值設(shè)置為最高收益。
          這樣循環(huán)完成之后最高收益就出來(lái)了,實(shí)現(xiàn)代碼如下:

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

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

          復(fù)雜度分析

          • 時(shí)間復(fù)雜度:O(n),只需要遍歷一次。
          • 空間復(fù)雜度:O(1),只使用了常數(shù)個(gè)變量。
          從以上的執(zhí)行的結(jié)果可以看出,這段代碼還算是比較理想的,這樣面試官也會(huì)對(duì)你豎起大拇指了。

          總結(jié)

          本文我們計(jì)算了單次(一次買入和賣出)股票的最高收益,剛開始我們使用的是最簡(jiǎn)單粗暴的暴力枚舉法,使用兩層循環(huán)依次相減來(lái)求出最高收益值,但這種方法的執(zhí)行效率太低。
          然后我們經(jīng)過(guò)觀察折線圖發(fā)現(xiàn),只需要一次循環(huán)也能找出最高的收益值。我們只需要在每個(gè)節(jié)點(diǎn)做兩個(gè)判斷,第一:判斷此節(jié)點(diǎn)是否為相對(duì)最小值,如果是,則記錄下來(lái);如果不是,則計(jì)算此值和相對(duì)最小值是否為當(dāng)前最高收益,如果是,則記錄下來(lái)。那么循環(huán)一圈之后,我們就能得出最高的收益了,并且執(zhí)行的效率也很高。
          你學(xué)會(huì)了嗎?有不懂的地方或者更好的方法,歡迎評(píng)論區(qū)留言~

          有道無(wú)術(shù),術(shù)可成;有術(shù)無(wú)道,止于術(shù)

          歡迎大家關(guān)注Java之道公眾號(hào)


          好文章,我在看??

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <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>
                  国产女孩骚逼AV重口免费大全 | 黄色成人在线 | 无码高清毛片 | 成年人看的毛片 | www伊人|