最近在刷leetcode,看到这个题目,觉得还蛮有意思,这里给出一个关于这个问题的递归的解法。
PS:递归的解法比较好理解,但有一个缺点就是算法的效率比较低(算法需要重复计算一些值),在数据量比较大的情况下,执行时间较长,在数据量较小的情况下,可以采用这种方法。
题目描述
题目: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.
题目的大致意思就是:你是一个很nb的强盗,打算偷一整条街,这条街上的每个屋子里面都有不同数量的钱,但是相邻的屋子的警报系统是相连的,如果你在同一个晚上同时偷了相邻的屋子,那么就会自动报警(这个厉害),所以你不能偷全部的屋子,那么现在给出你每个屋子的钱的数量(非负整数),需要你计算出你偷到的最大的钱的数量,同时不惊动警察。
解题思路
这个问题尝试了很多种解法,最终得到了一个简答的递归解法(假设是从左往右开始偷的)。
-
首先考虑这个只有1个屋子的情况,这种情况下很简单,结果就是一个屋子的钱的数量.
-
考虑有2个屋子的情况,这种情况下,情形也是简单的,只需要抢2个屋子中最大的值就行。
-
考虑有3个屋子的情况,这种情况下,存在2种方案:偷最中间的屋子(也就是第2个),或者偷第1个和第3个屋子,最终情况取两种方案中的最大值即可。
-
考虑有4个屋子及以上的情况(屋子数量 >= 4),这里为了简化,列出了只有4个屋子的情况。这里需要明确一点:第一个偷的一定是第1个屋子或者第2个屋子。开始分别考虑两种情况:
- 第一种情况:从第一个开始偷,那么这种情况下能够偷的最大值就是第一个屋子的钱数加上从第3个屋子以后开始偷的最大数量的和。
- 第二种情况:从第二个开始偷,那么这种情况下的能够偷的最大值就是第二个屋子的钱加上从第4个屋子开始以后偷的最大数量的和。
分别计算上述两种情况中的最大数量的值,取两者的最大值,就可以得出最大值。
数学表达式
下面我们用数学表达式来描述上面的思路,设length代表房子的总数量,nums为给出每个房子的钱数,数学表达式可以为:
代码实现
这里主要我们使用了Python来实现整个代码,直接贴代码。
def rob(nums: 'List[int]') -> int:
def getmax(temp: 'List[int]') -> int:
if len(temp) == 1:
return temp[0]
elif len(temp) == 0:
return 0
elif len(temp) == 2:
return max(temp[0], temp[1])
elif len(temp) == 3:
return max(temp[0] + temp[2], temp[1])
else:
temp1 = temp[0] + getmax(temp[2:])
temp2 = temp[1] + getmax(temp[3:])
return max(temp1, temp2)
return getmax(nums)