问题描述:
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
解析:
dp[0]:只有一间房屋,第一天所偷结果。dp[0]=nums[0]
dp[1]:有两间房屋,前两天所偷结果。dp[1]=max(nums[0],nums[1])
因此dp[k]含义:前k+1天所偷结果;nums[k]含义:第k+1天所偷结果
当第k+1天没偷时,前k+1天所偷结果为前k天所偷结果:dp[k]=dp[k-1]
当第k+1天偷了,那么第k天一定没偷,前k+1天所偷结果为前k-1天所偷结果与第k+1天所偷结果之和:dp[k]=dp[k-2]+nums[k]
综上所述,这是一个动态规划问题,找出边界条件
当只有一间房屋时,所偷金额最大值即为dp[0]=nums[0]
当有两间房屋时,所偷金额最大值为dp[1]=max(nums[0],nums[1])
因为依次遍历数组,在数组最后一个元素处即可得出最大值,所以最终答案为dp[n-1](前n天所偷结果),n为数组长度。
代码如下:
1 # 打家劫舍问题 2 def rob(nums): 3 ''' 4 5 :param nums: 6 :return: 7 ''' 8 size = len(nums) 9 dp = [0] * size 10 11 if size == 0: 12 return 0 13 14 if size == 1: 15 return nums[0] 16 17 dp[0] = nums[0] 18 dp[1] = max(nums[0], nums[1]) 19 20 for i in range(2, size): 21 dp[i] = max(dp[i - 2] + nums[i], dp[i - 1]) 22 23 return dp[size - 1]
需要注意的特殊情况:
当房屋数为0时,即数组为空数组时,此时应加额外条件进行判断,返回值为0;当房屋数为1时,为两者中最大值
复杂度分析:
时间复杂度:因为遍历了一遍数组,所以时间复杂度为O(n),n为数组长度
空间复杂度:O(1)。使用滚动数组,存储的是当前房屋的前两间房屋的最大值,而不需要存储整个数组,因此空间复杂度为O(1)