LeetCode 198.打家劫舍-簡單
1.題目
你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/house-robber
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
示例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 。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/two-sum
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。
2.解題
方法一:動態規劃
- 問題本質是求間隔一位的數字和的最大值
- 運用動態規劃的解題思路:
設計動態規劃的三個步驟:
1.將問題分解成最優子問題
2.用遞歸的方式將問題表述成最優子問題的解
3.自底向上的將遞歸轉換成迭代(函數遞歸是自頂向下) - 由題:前i+1個房屋的最大收益必然是前i-1個房子的收益+第i+1個房子的收益總和和前i個房子的收益中較大的那個,即有表達式:
- 於是可以遞推可以得到任意i個房屋的最大收益
- 邊界條件:輸入list爲空,則需返回0
- 複雜度分析:
時間複雜度 O(N): 只做了一次遍歷
空間複雜度 O(N): 申請了dp數組所需空間
class Solution:
def rob(self, nums: List[int]) -> int:
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
if n == 0:
return 0
dp = [0 for i in range(n+1)]
dp[1] = nums[0]
for i in range(1,n):
dp[i+1] = (max(dp[i-1]+nums[i], dp[i]))
return max(dp)
方法二:不申請空間,直接在nums上改值
- 複雜度分析:
時間複雜度 O(N): 只做了一次遍歷
空間複雜度 O(1)
class Solution:
def rob(self, nums: List[int]) -> int:
"""
:type nums: List[int]
:rtype: int
"""
n = len(nums)
if n == 0:
return 0
if n == 1:
return nums[0]
else: # 遞推的基礎必須準確初始化,nums[0]不需要改動,nums[1]需要改動,
nums[1] = max(nums[0], nums[1])
for i in range(2, n):
nums[i] = max(nums[i-2]+ nums[i],nums[i-1])
return nums[n-1]