<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>

          【騰訊面試題】熊出沒

          共 3633字,需瀏覽 8分鐘

           ·

          2021-07-04 08:53

          周五來了,即將快樂周末,今天就給大家分享一道有趣的算法題,希望能給大家?guī)硪粋€好心情~

          01
          故事起源
          故事,要從住在森林里的大熊發(fā)現(xiàn)了一個裝滿蘋果的山洞說起...

          牛牛碼特

          13:14

          85%

          微信(116)

          相親相愛一家熊??


          我發(fā)現(xiàn)一個山洞,里面有好多蘋果??,看起來很好吃的樣子~




          不過我們只能從洞口和洞尾拿蘋果,我們來比比看誰拿的蘋果重量最大吧~


          好啊好啊



          那我們趕快去山洞吧!


          熊熊們山洞之旅遇到的問題,歸納起來就是:給定一個裝滿蘋果的山洞,只能從洞口和洞尾拿蘋果,每輪兩只熊交替拿,并且只能拿一個,誰拿的蘋果總重量最大誰就獲勝,那誰會是最終的贏家呢?

          02
          問題剖析
          假定山洞里蘋果的分布為:1KG,3KG,14KG,7KG。

          直覺上來說,是不是我們每輪拿最大的,就一定贏?如果是這種策略,那么大熊第一輪拿7KG,此時的狀況就變成了:

          這時候很顯然,二熊會拿最右邊14KG的蘋果:
          現(xiàn)在山洞里只剩下1KG和3KG兩個蘋果,無論大熊拿哪一個,它手上蘋果總重量,也沒二熊的重。難道這是大熊的必輸局?

          那么,讓我們換種拿法,重來一遍。

          如果第一輪,大熊選擇拿第一個蘋果,那此時狀態(tài)就變成了:

          這個時候,二熊只能從3KG、7KG里面選,無論拿哪個,大熊第三輪拿到14KG都能獲勝。因此,只要開局拿1KG,大熊就是必勝的。

          所以說,每輪選最大這種策略行不通,我們還需要考慮到對后面蘋果的影響。

          相信經過這個分析,大家已經對題目比較清楚,甚至有點解題思路了吧?別著急,現(xiàn)在我們就一起來看看有哪些解決辦法吧。


          03
          花式取蘋果

          深度優(yōu)先遞歸法

          我們可以把問題抽象出來,大熊第一輪去取蘋果,是否能贏取決于兩個因素:一個是取的蘋果的重量,另一個是二熊對剩下的進行選擇。仔細一想,二熊面臨的問題,其實和大熊開始時是一模一樣的。這樣思路就很明顯了,我們可以用遞歸的方法去解決問題。

          下面這張圖,可以幫助我們輔助思考。
          我們從最右邊往左邊看,每一輪都選擇當前的最優(yōu)解,整個流程走下來,就是遞歸的實際執(zhí)行流程了。

          經過上述分析,代碼也很清晰明了:
          func CanFistBearWin(nums []int) bool {    return picker(0len(nums)-1, nums) >= 0}
          // i, j 表示當前子問題中,山洞左右從哪里開始func picker(i, j int, nums []int) int { if i == j {     return nums[i]    }    head := nums[i] - picker(i+1, j, nums)    end := nums[j] - picker(i, j-1, nums)    return max(head, end)}


          記憶化遞歸法

          問題雖然解決了,但是跑了一下測試用例,發(fā)現(xiàn)用時100ms以上。這樣看來,性能上是不是還有優(yōu)化空間呢?

          可以看到,圖上是有重復子問題的,那我們完全可以將子問題的解答記錄下來。等到后面再遇到的時候,直接返回結果,而不用再遞歸下去,這樣就可以節(jié)約大量時間了。


          動態(tài)規(guī)劃法

          在上面的分析中,我們已經把問題拆分為子問題,既然是子問題,又可以遞歸解決,那么就不由地會去想,能不能通過動態(tài)規(guī)劃,遞推解決?

          依照慣例,我們需要一個dp數(shù)組,在上面的分析中不難看出,這個數(shù)組應該是二維的,dp[i][j]就表示左邊起點為i,右邊起點為j的山洞,在先手的情況下,熊熊能拿多少KG的蘋果。


          既然要用動態(tài)規(guī)劃,那么一定要找到一個公式。我們前面分析過,如果大熊先手,是否能贏取決于兩個因素:一個是取的蘋果的重量,另一個是二熊對剩下的進行選擇。

          根據(jù)這兩個因素,我們可以轉化為下列公式:
          dp[i][j] = Max(nums[i]-dp[i+1][j], nums[j]-dp[i]dp[j-1])

          再結合下面的圖來進行推導。我們還是以四個蘋果為例,為蘋果從左到右編上號。

          0號位置對應的dp[0][0]就是其蘋果的重量,我們從1號位置開始,對每個位置往前遞推:

          ??紅蘋果配合代碼食用更佳:
          func CanFistBearWin(nums []int) bool {    // 提前計算數(shù)組長度,避免反復消耗    length := len(nums)    dp := make([][]int, length)    // 子數(shù)組初始化    for i := 0; i < length; i++ {        dp[i] = make([]int, length)        // 左右在一個點的情況,取了這個蘋果即可        dp[i][i] = nums[i]    }    // j表示山洞右側位置    for j := 1; j < length; j++ {        // i表示山洞左側位置        for i := j-1;  i >= 0; i-- {            head := nums[i] - dp[i+1][j]            end := nums[j] - dp[i][j-1]            dp[i][j] = max(head, end)        }    }    return dp[0][length-1] >= 0}
          果不其然,成功拿到了蘋果,熊熊開心地跳起了舞


          04
          熊熊復盤
          解決此類問題的核心思想,是將從洞兩端選擇蘋果這個問題抽離出來,成為子問題。然后,在此基礎上,我們建立了遞歸解法,根據(jù)實際運行的結果,使用記憶化搜索優(yōu)化,提高了性能。

          解決了問題就算完成任務了?我們的目標可是成為一名追求極致的工程師,當然會想還有沒有其它解決方案。于是,我們將同一種抽象模型,從遞歸轉換成遞推,玩了把動態(tài)規(guī)劃。

          換個角度看問題,生命會展現(xiàn)出另一種美。生活中不是缺少美,而是缺少發(fā)現(xiàn)。算法也一樣,同一個問題,學著用多個角度去思考、解決,你會發(fā)現(xiàn)它別樣的魅力!
          瀏覽 65
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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伊人久久综合蜜芽 | 四虎高清无码 | 台湾精品久久久久久久 | 一本色道久久综合无码 |