1. 程式人生 > >LeetCode 198. House Robber (房屋搶劫)

LeetCode 198. House Robber (房屋搶劫)

原題

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that 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: [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.

Example 2:

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

Reference Answer

思路分析

一般來說,給定一個規則,讓我們求任意狀態下的解,都是用動態規劃。這裡的規則是劫匪不能同時搶劫相鄰的屋子,即我們在累加時,只有兩種選擇:

  1. 如果選擇了搶劫上一個屋子,那麼就不能搶劫當前的屋子,所以最大收益就是搶劫上一個屋子的收益
  2. 如果選擇搶劫當前屋子,就不能搶劫上一個屋子,所以最大收益是到上一個屋子的上一個屋子為止的最大收益,加上當前屋子裡有的錢

所以,我們只要判斷一下兩個裡面哪個大就行了,同時也是我們的遞推式。另外我們可以做一點優化,本來我們是要用一個dp陣列來儲存之前的結果的。但實際上我們只需要上一次和上上次的結果,所以可以用兩個變數就行了。

自己開始竟然天真地以為直接算奇數索引項與偶數索引項求和比較即可,too young too simpy,畢竟[2,1,1,3]的輸出應該是5,而非4。

Code

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]
        pre_max = nums[0]
        current_max = max(nums[0], nums[1])
        for index,count in enumerate(nums[2:]):
            temp = current_max
            current_max = max(pre_max+count, temp)
            pre_max = temp
        return max(pre_max, current_max)
        # for index, count in enumerate(nums):
        #     if index % 2 == 0:
        #         nums_even += count
        #     else:
        #         nums_odd += count
        # return max(nums_even, nums_odd)
        
#         nums_odd = list(filter(lambda c: nums.index(c) % 2 == 0, nums))
#         nums_even = list(filter(lambda c: nums.index(c) % 2 == 1, nums))
#         return max(sum(nums_even), sum(nums_odd))

Note:

  • 這道題開始嘗試使用filter函式得到只含奇數索引項與偶數索引項的list,模仿
    # filter函式和map相似,但是filter是返回布林值去去輸入列表進行判斷
    res = list(filter(lambda c: res.count(c) == 1, res))
    
    用了nums_odd = list(filter(lambda c: nums.index(c) % 2 == 0, nums))宣告失敗,因為filter函式是針對index進行的判別,故而輸出的也是index值,而非index對應的list項;

參考資料

[1] https://segmentfault.com/a/1190000003811581