1. 程式人生 > >【LeetCode】213. House Robber ||

【LeetCode】213. House Robber ||

213. House Robber II

Description:

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night

.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2),
             because they are adjacent houses.

Example 2:

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
             Total amount you can rob = 1 + 3 = 4. 

解題思路:

分析:

由於最後一個房子和第一個房子相鄰,那麼就會出現兩種情況:

1)搶劫第一個房子的時候,不能搶劫最後一個房子。這種情況下,就是從輸入序列中去除最後一個房子,也就是求輸入序列的子序列中搶劫錢數最多,即求序列[6, 6, 0, 3, 1]。

2)搶劫最後一個房子的時候,不能搶劫第一個房子。這種情況下,就是從輸入序列去除第一個房子,也就是求輸入序列的子序列中搶劫錢數最多,即求序列[6, 0, 3, 1, 9]。

因此:

通過對上面的兩種情況的分析,每一種情況都是這道題(【LeetCode】198. House Robber)的輸入,我們可以把這道題的結果封裝成一個函式,對上面兩種情況分別進行輸入計算即可。

(1)動態規劃解法:

已經AC的程式碼:

class Solution:

    def __init__(self):
        self.arr = []

    def rob(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums) == 0:
            return 0
        if len(nums) == 1:
            return nums[0]
        if len(nums) == 2:
            return max(nums[0], nums[1])
        self.arr = [0 for _ in range(len(nums))]
        return max(self.getRob(nums, self.arr, 0, len(nums)-2),
                   self.getRob(nums, self.arr, 1, len(nums)-1))

    def getRob(self, nums, arr, start, end):
        """
        :param nums: list[int]
        :param arr:  list[int]
        :param start: int
        :param end: int
        :return:
        """
        arr[start] = nums[start]
        arr[start + 1] =max(nums[start], nums[start + 1])
        for i in range(start+2,end + 1):
            arr[i] = max(nums[i] + arr[i - 2], arr[i - 1])
        return  arr[end]

solution = Solution()
# test 1
# nums = []
# test 2
# nums = [2, 3]
# test 3
nums = [2, 3, 2]
print(solution.rob(nums))

​​AC之後,感覺自己寫程式碼不夠簡潔,參考https://leetcode.com/problems/house-robber-ii/discuss/196728/python-dp-solution,優化程式碼後為:

已經AC的程式碼:

class Solution:

    def rob(self, nums):
        """
        :param nums: list[int]
        :return:
        """
        if len(nums) == 0: return  0
        if len(nums) == 1: return  nums[0]
        if len(nums) == 2: return  max(nums)
        def getRob(start, stop, nums):
            n = nums[start: stop + 1]
            dp = [0] * len(n)
            dp[0], dp[1] = n[0], max(n[0], n[1])
            for i in range(2, len(n)):
                dp[i] = max(dp[i - 1], dp[i - 2] + n[i])
            return dp[-1]
        return  max(getRob(0, len(nums) - 2, nums), getRob(1, len(nums) - 1, nums))

solution = Solution()
# test 1
# nums = []
# test 2
# nums = [2, 3]
# test 3
nums = [2, 3, 2]
print(solution.rob(nums))