2026-10-20 09:15:28
打家劫舍问题是一类经典的动态规划问题,主要考察如何在满足特定约束条件下最大化收益。以下是针对不同打家劫舍问题的详细解答:
1. 打家劫舍 I(LeetCode 198)问题描述:给定一个非负整数数组,表示每个房屋中的金额。不能同时抢劫相邻的房屋,求能抢劫的最大金额。
方法一:深度优先遍历(记忆化搜索)
将问题抽象为二叉树,每个节点有两个选择:偷或不偷。使用记忆化搜索避免重复计算。
class Solution: def rob(self, nums: List[int]) -> int: n = len(nums) memo = [-1] * n def dfs(i): if i >= n: return 0 if memo[i] != -1: return memo[i] left = dfs(i + 1) right = dfs(i + 2) memo[i] = max(left, right + nums[i]) return memo[i] return dfs(0)方法二:动态规划
使用动态规划数组 dp,其中 dp[i] 表示前 i 个房屋能抢劫的最大金额。
class Solution: def rob(self, nums: List[int]) -> int: n = len(nums) if n == 1: return nums[0] if n == 2: return max(nums[0], nums[1]) 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 - 1], dp[i - 2] + nums[i]) return dp[n - 1]2. 打家劫舍 II(LeetCode 213)问题描述:房屋围成一圈,即第一个和最后一个房屋相邻。不能同时抢劫相邻的房屋。
方法:将问题拆分为两个子问题:
问题描述:房屋排列成二叉树,不能同时抢劫直接相连的两个房屋。求能抢劫的最大金额。
方法:使用深度优先遍历(DFS),对于每个节点,返回两个值:
这些方法均基于动态规划思想,通过合理定义状态和状态转移方程,高效解决问题。