题目来源:
https://leetcode-cn.com/problems/house-robber-ii/description/
题意分析:
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
示例 1:
输入: [2,3,2]输出: 3解释: 你不能先偷窃 1 号房屋(金额 = 2) ,然后偷窃 3号房屋 (金额 = 2), 因为他们是相邻的。
示例 2:
输入: [1,2,3,1]输出: 4解释: 你可以先偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
题目思路:
对于给定的列表,我们只选择第一或第二个元素,因为如果选择第三个会得到更大的值,那么由于可以隔一个元素偷窃,那么第一个元素必定可以被选择。在选定元素后,可以递归调用函数,列表起点为该元素之后的第二个元素,以此进行。为了使算法复杂度降低,再设定一个字典记录已经得到的从某起点开始的列表最大的值。
python代码如下:
class Solution:
def __init__(self):
self.nums_dict = {}
def rob0(self, house_lists, head):
if len(house_lists) > 3:
index = 0
sum_now = 0
while index < 2:
if head+index+2 not in self.nums_dict.keys():
self.nums_dict[head+index+2] = self.rob0(house_lists[index+2:],head+index+2)
sum_temp = self.nums_dict[head+index+2] + house_lists[index]
if sum_temp > sum_now:
sum_now = sum_temp
index += 1
return sum_now
if len(house_lists) == 1:
return house_lists[0]
if len(house_lists) == 2:
if house_lists[0] > house_lists[1]:
return house_lists[0]
return house_lists[1]
if len(house_lists) == 3:
if house_lists[0] + house_lists[2] > house_lists[1]:
return house_lists[0] + house_lists[2]
return house_lists[1]
def rob(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
if not nums:
return 0
if len(nums) == 1:
return nums[0]
sum1 = self.rob0(nums[0:len(nums) - 1],0)
self.nums_dict = {}
sum2 = self.rob0(nums[1:],1)
if sum1 > sum2:
return sum1
return sum2