198. 打家劫舍(Python)

題目

難度:★★☆☆☆
類型:數學

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。

給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

示例

示例 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. 定義向量dp
    dp向量長度與輸入數組nums相同,dp[i]表示到第下標為i的房屋位置,可以打劫到的最大金額;

  2. 初始條件
    (1)當i=0時,打劫到第一家為止最大的打劫金額為這一家的金額,即dp[0]=nums[0]
    (2)當i=1時,由于相鄰房屋不能同時打劫,因此打劫到第二家位置的最大打劫金額為前兩家中的最大值,即dp[1]=max(nums[0], nums[1])

  3. 狀態轉移方程
    當i>=2時,當前的總金額有兩種情況:
    (1)如果打劫下標為i的房間,這樣下標為i-1的房間不能打劫,則當前的最大總金額為打劫到i-2房間的金額與下標為i的房間的金額之和;
    (2)不打劫下標為i的房間,則當前的最大金額等于打劫到i-1房間的最大金額;
    取兩個選擇的最大值,因此有:
    dp[i] = max(dp[i-2] + nums[i], dp[i-1])

具體編碼實現如下:

class Solution(object):
    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:                                    # 沒有家舍
            return 0
        
        if len(nums) == 1:                              # 只有一家
            return nums[0]

        dp = [0 for _ in range(len(nums))]              # 定義dp
        dp[0], dp[1] = nums[0], max(nums[0], nums[1])   # 并初始化
        
        for i in range(2, len(nums)):                   # 從第3家開始循環到最后一家
            dp[i] = max(dp[i-2]+nums[i], dp[i-1])       # 狀態轉移方程

        return dp[-1]                                   # 返回最后結果

如有疑問或建議,歡迎評論區留言~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 人生何懼,瘦有何難
    Ada_YYYYYY閱讀 272評論 0 0
  • 黑鏡第三季第二集觀看 陰謀論 為啥我在看到男主在一夜情后,信用卡被盜刷,回到女方家,被提議偷拍時,有種陰謀籠罩的感...
    Chronus閱讀 476評論 0 0
  • 文圖/野笛文貝 福建省霞浦縣是有千年歷史的沿海縣,縣城所在地松城街道南部的山河,樹綠花紅,小橋流水,成為縣城一道靚...
    文貝閱讀 556評論 7 38
  • 1 如何導入外部數據庫 把原數據庫包括在項目源碼的 res/rawandroid系統下數據庫應該存放在 /data...
    NiceDream閱讀 228評論 0 1