pydata

Keep Looking, Don't Settle

leetcode 198. House Robber

198. House Robber

题目大意,一个强盗沿着一排房子盗窃,强盗不能盗连续的两个房子,求强盗能盗窃的最大值. 比如6个房子,强盗抢劫每个房子得到的值为 nums = [3, 1, 5, 3, 7, 9]。最大获利为 3 + 5 + 9 = 17.

解题思路:

这个题如果用brute force直接解的话会超时,brute force每个房子有两个可能,robber or not,所以n个房子的时间复杂度是\(O(2^n)\)。直接超时。

可以用动态规划来解:

假设 d[i] = max money for up to ith home

那么 d[i] = max(d[i - 1], d[i - 2] + nums[i])

这种题目通常可以用记忆化递归,或者递推来解。通常可以进行空间压缩。

1. recursion with memorization

class Solution(object):
    def rob(self, nums):
        n = len(nums)
        res = [-1 for _ in range(n)]
        def dp(nums, i, res):
            if i < 0:
                return 0
            if res[i] >= 0:
                return res[i]
            else:
                res[i] = max(dp(nums, i - 1, res), dp(nums, i - 2, res) + nums[i])
            return res[i]
        return dp(nums, n - 1, res)

2. 递推/动态规划

class Solution(object):
    def rob(self, nums):
        n = len(nums)
        if n == 0:
            return 0
        if n == 1:
            return nums[0]
        d = [0 for _ in range(n)]
        d[0] = nums[0]
        d[1] = max(nums[0], nums[1])
        for i in range(2, n):
            d[i] = max(d[i - 1], d[i - 2] + nums[i])
        return d[n - 1]

3. 递推/动态规划 + 压缩空间

class Solution(object):
    def rob(self, nums):
        n = len(nums)
        if n == 0:
            return 0
        dp1 = 0
        dp2 = 0
        for i in range(n):
            curr = max(dp1, dp2 + nums[i])
            dp2 = dp1
            dp1 = curr
        return curr