1. 打家劫舍问题解析
打家劫舍(House Robber)是LeetCode上经典的动态规划问题,编号为198。题目描述如下:假设你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。
1.1 问题理解与建模
这个问题可以抽象为一个序列选择问题:给定一个非负整数数组nums,我们需要从中选取一个子序列,使得:
- 不能选取相邻的元素
- 选取的元素之和最大
例如,对于输入[1,2,3,1],最优解是选择第1和第3个房屋(1+3=4);对于[2,7,9,3,1],最优解是选择第1、3、5个房屋(2+9+1=12)。
1.2 动态规划思路
这类问题通常可以使用动态规划(Dynamic Programming,DP)来解决。动态规划是一种分阶段解决问题的方法,它将原问题分解为若干子问题,通过解决子问题来最终解决原问题。
对于打家劫舍问题,我们可以定义dp[i]表示前i个房屋能够偷窃到的最高金额。那么状态转移方程可以这样考虑:
对于第i个房屋,我们有两个选择:
- 偷窃第i个房屋:那么就不能偷窃第i-1个房屋,此时总金额为dp[i-2] + nums[i-1]
- 不偷窃第i个房屋:那么总金额保持为dp[i-1]
我们需要在这两个选择中取最大值,因此状态转移方程为:
dp[i] = max(dp[i-1], dp[i-2] + nums[i-1])
初始条件为:
dp[0] = 0 (没有房屋可偷)
dp[1] = nums[0] (只有一间房屋时只能偷它)
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 代码实现与解析
2.1 TypeScript实现
typescript复制function rob(nums: number[]): number {
let n = nums.length;
let dp = new Array(n + 1).fill(0);
dp[1] = nums[0];
for(let i = 2; i <= n; i++) {
dp[i]
