1. 程式人生 > >【LeetCode 簡單題】51-打家劫舍

【LeetCode 簡單題】51-打家劫舍

宣告:

今天是第51道題。模擬小偷打劫沿街的房屋,每個房屋有非負的現金可取,但如果相鄰打劫會觸發報警,問如何不觸發報警裝置的情況下打劫到最大的金額。以下所有程式碼經過樓主驗證都能在LeetCode上執行成功,程式碼也是借鑑別人的,在文末會附上參考的部落格連結,如果侵犯了博主的相關權益,請聯絡我刪除

(手動比心ღ( ´・ᴗ・` ))

正文

題目:你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。給定一個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情況下,

能夠偷竊到的最高金額。

示例 1:

輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
     偷竊到的最高金額 = 1 + 3 = 4 。

示例 2:

輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接著偷竊 5 號房屋 (金額 = 1)。
     偷竊到的最高金額 = 2 + 9 + 1 = 12 。

解法1。這是一個動態規劃問題,無非就是滿足前提的情況下當前遍歷元素要不要加到金額當中(對應要不要打劫這一家),前提就是當前元素金額必須和前2個元素之前的相累加,那麼就轉化為比較大小的問題,用1個數組max_profit存放每一步的最優結果,比如說max_profit[2]存放的是遍歷到第3個元素時,此時能打劫到的最大金額,落實程式碼中就是比較出當前nums[3]+max_profit[1]和max_profit[2]的大小,有以下幾個要點:

  • 求全域性最優的過程可以轉化為求區域性最優,也就是說求最大的打劫金額可以轉化為求第1步、第2步、第3步的最優解,而這些最優解都是由前面求出的決定的,所以只要確認好邊界條件就是成功的一半,第1步最大金額就是第1個值即nums[0],第2步最大金額是nums[0]和nums[1]的最大值,第3步的最大金額是max_profit[1]+nums[3]和max_profit[2]的最大值
  • 用1個數組存放每一步的最大金額

耗時28 ms, 在House Robber的Python提交中擊敗了58.61% 的使用者,程式碼如下。

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        max_profit = [0 for i in range(len_n)]    # 必須初始化,否則後面存放資料時無法通過index索引。為全0,元素個數和nums的一樣
        len_n = len(nums)
        if len_n == 0:
            return 0
        if len_n == 1:
            return nums
        if len_n == 2:
            return max(nums)    # 原來nums只有2個元素時,可以直接傳入整個nums,不必寫成max(nums[0],nums[1])
        else:
            max_profit[0] = nums[0]
            max_profit[1] = nums[1]
            for i in range(2,len_n):
                max_profit[i] = max(max_profit[i-1], max_profit[i-2]+nums[i])
        return max_profit[-1] # 返回最後1個元素,即對應輸入nums有n個元素時的最大金額

解法2。看下效率最高的解法,可能是環境的原因,我把結果貼上過來執行結果耗時32ms,解法差不多,不過邏輯寫得較簡潔,可以注意一下,耗時20ms,程式碼如下。

 

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
       
        if len(nums) == 0:
            return 0
        elif len(nums) < 2:
            return max(nums[0], nums[-1])
        money = [0]*len(nums)
        money[0],money[1] = nums[0], max(nums[0], nums[-1]
        for i in range(2,len(nums)-1):
            money[i] = max(money[i-2]+nums[i], money[i-1])
        return money[len(nums)-1]
            

結尾

解法1:https://blog.csdn.net/m0_37477175/article/details/80038517

解法2:LeetCode-提交成功後點擊檢視詳情連結-可以看自己的用時排名和所有人提交的程式碼