Leetcode上面的打家劫舍和打家劫舍 Ⅱ是很是典型的DP題目。數組
Leetcode 198code
你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有必定的現金,影響你偷竊的惟一制約因素就是相鄰的房屋裝有相互連通的防盜系統,若是兩間相鄰的房屋在同一夜被小偷闖入,系統會自動報警。給定一個表明每一個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的狀況下,可以偷竊到的最高金額。ip
示例 1:leetcode
輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,而後偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。get示例 2:io
輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5 號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。class
首先找出遞推關係List
對於每一個房屋的arr[]
一間屋 返回arr[0]
兩間屋 返回max(arr[0],arr[1])
屋子數量大於三時:
arr[-1]
)不偷,那麼能夠獲得的最大金額爲前len(arr)-1
個arr[]
能夠偷竊的最大金額.len(arr)-2
個arr[]
能夠獲取的金額 + arr[-1]偷竊的金額.爲了下降代碼時間複雜度,使用數組記憶大小爲1->numsSize時的子問題的結果,用於計算父問題。時間
代碼實現爲:co
int rob(int *nums, int numsSize) { if (numsSize <= 0) { return 0; } if (numsSize == 1) { return nums[0]; } int arr[1000]; arr[0] = nums[0]; arr[1] = nums[1] > nums[0] ? nums[1] : nums[0]; int a = nums[2] + arr[0]; int b = nums[1]; arr[2] = a > b ? a : b; for (int i = 3; i < numsSize; i++) { int x = nums[i] + arr[i - 2]; int y = nums[i - 1] + arr[i - 3]; arr[i] = x > y ? x : y; } return arr[numsSize - 1]; }
Leetcode 213
你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有必定的現金。這個地方全部的房屋都圍成一圈,這意味着第一個房屋和最後一個房屋是緊挨着的。同時,相鄰的房屋裝有相互連通的防盜系統,若是兩間相鄰的房屋在同一夜被小偷闖入,系統會自動報警。
給定一個表明每一個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的狀況下,可以偷竊到的最高金額。
示例 1:
輸入: [2,3,2]
輸出: 3
解釋: 你不能先偷竊 1 號房屋(金額 = 2),而後偷竊 3 號房屋(金額 = 2), 由於他們是相鄰的。示例 2:
輸入: [1,2,3,1]
輸出: 4
解釋: 你能夠先偷竊 1 號房屋(金額 = 1),而後偷竊 3 號房屋(金額 = 3)。偷竊到的最高金額 = 1 + 3 = 4 。
這道題相對於上一題稍有變化,主要是由於圓形的房屋排布的緣由,第一與最後一個房屋不能同時偷竊,因此第一和最後一個房屋不能同時出現,因此分爲兩種狀況:
class Solution: def rob(self, nums): """ :type nums: List[int] :rtype: int """ if len(nums) == 0: return 0 if len(nums) == 1: return nums[0] return max(self.subrob(nums[1:]), self.subrob(nums[:-1])) def subrob(self, nums): # for i in nums n = len(nums) ll = [0 for i in range(n)] # 建立數組 if n == 0: return 0 if n == 1: return nums[0] ll[0] = nums[0] ll[1] = max(nums[0], nums[1]) for i in range(2, n): ll[i] = max(ll[i - 2] + nums[i], ll[i - 1]) return ll[n - 1]