LeetCode 213:打家劫舍 II(House Robber II)—— 题解 ✅

LeetCode 213:打家劫舍 II(House Robber II)------ 题解 ✅

📖 内容概要

你是一个专业的小偷,计划偷窃沿街的房屋。

所有房屋围成一圈 ,这意味着第一间房和最后一间房相邻。

如果两间相邻的房屋在同一晚上被闯入,系统会自动报警。

求在不触动警报的前提下,一夜之间能够偷窃到的最高金额

✅ 动态规划

✅ 环状结构拆环

✅ 基于 LeetCode 198 的变形


💡 解题思路(核心)

一、关键难点:环形限制

由于房屋是 环形

  • 偷了第 1 间 → 不能偷第 n 间
  • 偷了第 n 间 → 不能偷第 1 间

二、拆环为链(核心思想)

将环形问题拆分为两个线性问题:

情况 偷窃范围
情况 1 第 1 间 ~ 第 n-1 间
情况 2 第 2 间 ~ 第 n 间

✅ 两种情况互不冲突

✅ 分别用「打家劫舍 I」求解

✅ 取最大值


三、状态转移(复用 198)

java 复制代码
dp[i] = max(
    dp[i - 1],          // 不偷当前
    dp[i - 2] + nums[i] // 偷当前
)

✅ AC 代码(Java)

java 复制代码
class Solution {
    public int rob(int[] nums) {
        int len = nums.length;
        if (len == 1) {
            return nums[0];
        }

        // 拆成两个线性问题
        int[] a = Arrays.copyOf(nums, len - 1);      // 不含最后一间
        int[] b = Arrays.copyOfRange(nums, 1, len); // 不含第一间

        return Math.max(help(a), help(b));
    }

    // 线性打家劫舍(198 题)
    public int help(int[] nums) {
        int len = nums.length;
        if (len == 1) {
            return nums[0];
        }

        int[] dp = new int[len];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);

        for (int i = 2; i < len; i++) {
            dp[i] = Math.max(
                dp[i - 1],
                dp[i - 2] + nums[i]
            );
        }
        return dp[len - 1];
    }
}

⏱️ 复杂度分析

指标 复杂度
时间复杂度 O(n)
空间复杂度 O(n)(可优化为 O(1))

🔍 与「打家劫舍 I」的对比

题目 结构 解法
198 线性街道 一次 DP
213 环形 拆成两个线性 DP

✅ 一句话总结

环形 = 去掉第一家 or 去掉最后一家,取两者最大值。


📌 面试加分点(建议记住)

  • ✅ 为什么不能直接用线性 DP?
  • ✅ 为什么拆成两段就一定正确?
  • ✅ 如何进一步优化空间?
  • ✅ 与树形 DP(337)的区别
相关推荐
三品吉他手会点灯1 小时前
C语言学习笔记 - 44.运算符和表达式 - 运算符2 - 除法与取余运算符
c语言·开发语言·笔记·算法
乐迪信息1 小时前
乐迪信息:AI算法盒子实时识别船舶烟雾与火焰异常
大数据·人工智能·算法·安全·目标跟踪
J-Tony111 小时前
【JVM】根可达算法
jvm·算法
艾iYYY1 小时前
string 类的模拟实现
android·服务器·c语言·c++·算法
Lsk_Smion2 小时前
力扣实训 _ [75].颜色分类 _ 杨辉三角
数据结构·算法·leetcode
jidaowansui2 小时前
P11375 [GESP202412 六级] 树上游走
数据结构·算法
cuso4win3 小时前
Feed 流面试笔记
笔记·面试·职场和发展
小蒋聊技术3 小时前
电商系列第九课:结算中心 —— 电商财务底盘,资金分账与 AI 智能化演进
人工智能·面试·职场和发展