算法第十八天-打家劫舍Ⅱ

打家劫舍Ⅱ

题目要求

解题思路

  • 打家劫舍Ⅱ是说两个相邻的房间不能同时偷,并且首尾两个房间是相邻的(不能同时偷首尾房间)
  • 明显是基于打家劫舍Ⅰ做的升级。打家劫舍Ⅰ也是说两个相邻的房间不能同时偷,但是首尾房间不是相邻的(可以同时偷首尾房间)

所以,我们先从打家劫舍Ⅰ开始说起。

打家劫舍Ⅰ

题目:两个相邻的房间不能同时偷,首尾房间不相邻,求小偷能获取的最大金额。

对于求数组中按照某种方法进行选择,求最值,而不用知道具体选择方案的问题,可以考虑动态规划。动态规划最基本的是状态的定义,然后比较困难的是状态转移方程

状态定义dp[i],一般可以根据题意,题目要求什么,我们就定义什么。比如本题,我们定于dp[i]数组的前i个元素 中按照两个相邻的房间不能同时偷的方法,能够获得到的最大值。(经验:定义dp[i]为数组的前i个元素的结果)

考虑状态转移方程是,一定要想办法让dp[i]能够基于dp[0~i-1]生成。本题要求不能同时偷相邻的房间。所以,dpi有两种选择:numi选或者不选。

  • 如果num[i]选,那么由于不能选择相邻的房间,所以不可以选择num[i-1],所以选择num[i]的情况下,数组的前i个元素构成的最大值dp[i]=dp[i-2]+num[i];
  • 如果num[i]不选,那么就可以选择num[i-1],所以数组的前i个元素构成的最大值 等于 数组前i-1个元素构成的最大值,即dp[i]=dp[i-1]
  • 所以,最终的dp[i]是上面两种情况的最大值。

初始条件比较简单:

  • dp[0] = num[0]
  • dp[1] = max(dp[0],num[1]) = max(num[0], num[1])

返回结果,可以根据我们的dp[i]知道最终要求的是在整个数组上能够取得的最大值。所以返回dp[N-1]

打家劫舍Ⅱ

在多了数组的开头和结尾是相邻的情况下,也就是说,数组的开头和结尾元素不能同时选。由于状态转移方程中,是没有标记我们到底选了哪些元素的。所以如果想通过状态转移方程,来实现首尾元素不能同时选,是很难的。

这里就用上了技巧,分为两种情况去考虑:分别在nums[0:N-1]上计算能获得到的最大值,这两种个情况取最大。这肯定能保证在物理上隔离了首尾两个元素,肯定不会同时选到。

代码

python 复制代码
class Solution:
    def rob(self, nums: List[int]) -> int:
        N = len(nums)
        if not nums:
            return 0
        if N == 1:
            return nums[0]
        return max(self.rob1(nums[0:N - 1]), self.rob1(nums[1:N]))
    def rob1(self,nums:List[int]):    
        N = len(nums)
        if not nums:
            return 0
        if N == 1:
            return nums[0]
        # max amount [0, i]
        dp = [0] * N
        dp[0] = nums[0]
        dp[1] = max(nums[0], nums[1])
        for i in range(2, N):
            dp[i] = max(dp[i - 2] + nums[i], dp[i - 1])
        return dp[-1]

复杂度分析

时间复杂度: O ( N ) O(N) O(N)

空间复杂度: O ( 1 ) O(1) O(1)

相关推荐
fqq312 分钟前
力扣刷题前置Java语法
算法·leetcode·职场和发展
2501_906565123 小时前
数学之美探究
算法
oier_Asad.Chen3 小时前
【洛谷题解/AcWing题解/OI学习笔记】洛谷P2868【USACO07DEC】Sightseeing Cows G(01分数规划求最大比率)
算法·图论·spfa·二分·负环
leisoo80975 小时前
财报数据怎么排雷本地化Python构建财务异常预警系统
人工智能·python·算法
luj_17687 小时前
塔防牌:策略与卡牌的智慧碰撞
服务器·c语言·开发语言·经验分享·算法
郝学胜-神的一滴7 小时前
干货版《算法导论》17:二叉树核心原理、遍历逻辑与高阶实操全解
数据结构·c++·python·算法·计算机·编程
爱编程的小新☆8 小时前
【LeetCode】从递归到 Flood Fill:5 道题吃透 DFS 的选择、回溯与标记
java·算法·leetcode·深度优先·回溯·flood fill
Water_Sunzhipeng8 小时前
2024牛客暑期多校训练营1
算法
hetao17338378 小时前
2026-08-09~08-14 hetao1733837 的刷题记录
c++·算法
技术小黑8 小时前
RNN算法实战系列06 | LSTM 实现糖尿病探索与预测
rnn·算法·lstm