1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        LeetCode 啥題都有:Go 刷「打家劫舍」

        共 2828字,需瀏覽 6分鐘

         ·

        2021-05-20 01:11

        這個刷題板塊又?? 了好久,這不又重新安排上了,上次我們最后刷的是一道動態(tài)規(guī)劃的題目:Leetcode-198. 打家劫舍I ,今天我們來看它的進(jìn)階版II。

        介紹


        這是 House Robber II,也就是 I 的變型版本。II 和 I 的最大區(qū)別在于 II 把房子圍成一個圈了這意味著第一幢房子和最后一幢房子是緊挨著的。根據(jù)規(guī)則,兩間相鄰的房子不能同時偷,小偷打擊還是蠻大的

        小偷在不觸發(fā)報警裝置的情況下,針對這類場景,如何讓自己偷竊的利益最大化?


        解題

        上面提到,相鄰兩家不能同時偷。但是如果只有一家,那么構(gòu)不成相鄰的條件,就偷唯一的那戶人家。 


        如果有兩家,那么偷的必然是兩家中錢多的那家。


        那如果總數(shù)大于 2 家呢?


        對于第 n 家來說,只有兩種選擇:偷或者不偷。


        是咋么計算出當(dāng)前這家是否要偷的呢。


        我們假設(shè)當(dāng)前這家編號為 n,那么,


        max(偷第 n 家的錢 + dp[截止第 n-2 家偷的錢], dp[截止第 n-1 家偷的錢])。


        這才是這道關(guān)于動態(tài)規(guī)劃最核心的一個點。

        看懂了嗎?沒看懂也沒關(guān)系,手把手摸個圖片出來。 

        還沒看懂,加我微信 remember_wuqinqiang 我告訴你。這里順便打個廣告,沒加我好友的趕緊加我好友。

        最后,還需要考慮一個問題,如何確保偷了第一家就不偷最后一家,偷最后一家就不偷第一家的情況。 很簡單,直接定義兩個 dp,一個范圍不包括第一家,一個范圍不包括最后一家。 最后我們變成了求:


        // 偽代碼
        最佳偷錢:=max(dp[不包括第一家],dp[不包括最后一家])


        那么剩下的就是對兩個 dp 的狀態(tài)轉(zhuǎn)移公式了。

        func rob(nums []int) int {
          n := len(nums)
          if n == 0 {
            return 0
          }
          if n == 1 {
            return nums[0]
          }

          dp1, dp2 := make([]int, n), make([]int, n)

          dp1[0] = nums[0]
          dp1[1] = max(dp1[0], nums[1])

          dp2[0] = 0 //dp2 不偷第一家
          dp2[1] = max(dp2[0], nums[1])

          for i := 2; i < n; i++ {
            if i < n-1 { // dp1 不偷最后一家
              dp1[i] = max(dp1[i-1], dp1[i-2]+nums[i])
            } else {
              dp1[i] = dp1[i-1]
            }
            dp2[i] = max(dp2[i-1], dp2[i-2]+nums[i])
          }
          return max(dp2[n-1], dp1[n-1])
        }

        func max(x int, y int) int {
          if x > y {
            return x
          }
          return y
        }

        其實代碼還能更簡潔。

        func rob(nums []int) int {
          n := len(nums)
          if n == 0 {
            return 0
          }

          if n == 1 {
            return nums[0]
          }
          if n == 2 {
            return max(nums[0], nums[1])
          }
          return max(helper(nums[1:]), helper(nums[:n-1]))
        }

        func helper(nums []int) int {
          first, second := nums[0], max(nums[0], nums[1])
          for _, v := range nums[2:] {
            first, second = second, max(second, first+v)
          }
          return second
        }

        func max(a, b int) int {
          if a > b {
            return a
          }
          return b
        }


        今天的題就分享到這了。



        推薦閱讀


        福利

        我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號 「polarisxu」,回復(fù) ebook 獲??;還可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

        瀏覽 52
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

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

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            天天撸在线观看 | 日本少妇AA一级特黄大片 | 蜜桃成人网站 | 中文字幕一区二区三区免费2023 | 日本高清不卡视频 | 熟女乱伦视频 | 啊轻点灬太粗嗯太深了用力音频 | 日韩 国产 制服 综合 无码 | japanesefree性公交车上 | 性生交大片免费看一女三男 |