class Solution:
def rob0(self, nums: List[int]) -> int:
dp =[0]*(len(nums)+1)
dp[0]=0
dp[1]=nums[0]
for i in range(2,len(nums)+1):
dp[i]=max(dp[i-1],dp[i-2]+nums[i-1])
return dp[-1]
def rob(self, nums: List[int]) -> int:
if len(nums)<=1:
return nums[0]
nums_with_first =nums[0:len(nums)-1]
nums_without_first =nums[1:len(nums)]
result= max(self.rob0(nums_with_first),self.rob0(nums_without_first))
return result
from typing import List # 确保导入 List 类型
class Solution:
# 辅助函数:解决线性排列的“打家劫舍 I”问题
def rob0(self, nums: List[int]) -> int:
"""
计算线性排列的房屋 nums 中能偷窃到的最高金额。
假设调用此函数时,nums 列表长度至少为 1 (由主函数 rob 保证)。
"""
n = len(nums)
# 因为主函数 rob 保证了调用此函数时 n >= 1,
# 我们可以简化这里的边界处理。
# 如果 n == 0: return 0 (理论上不会发生)
if n == 1:
return nums[0] # 如果只有一个房子,直接返回其金额
# 创建 DP 数组,大小为 n+1
# dp[i] 表示考虑前 i 个房子 (索引 0 到 i-1) 能偷到的最大金额
dp = [0]*(n + 1)
# dp[0] = 0: 不偷任何房子,金额为 0
dp[0] = 0
# dp[1]: 只考虑第一个房子 (nums[0]),最大金额就是 nums[0]
dp[1] = nums[0]
# 从第 2 个房子开始计算 (对应 nums 索引为 1,dp 索引为 2)
for i in range(2, n + 1):
# 递推关系:
# 偷第 i 个房子 (nums[i-1]) 的最大金额 = dp[i-2] + nums[i-1]
# 不偷第 i 个房子 (nums[i-1]) 的最大金额 = dp[i-1]
# 取两者中的较大值
dp[i] = max(dp[i-1], dp[i-2] + nums[i-1])
# 返回考虑所有 n 个房子的最大金额,即 dp[n]
# dp[-1] 是 Python 访问列表最后一个元素的便捷方式,即 dp[n]
return dp[-1]
# 主函数:解决环形排列的“打家劫舍 II”问题
def rob(self, nums: List[int]) -> int:
"""
计算环形排列的房屋 nums 中能偷窃到的最高金额。
第一个房子和最后一个房子不能同时偷。
"""
n = len(nums)
# --- 边界情况处理 ---
# 如果没有房子
if n == 0:
return 0
# 如果只有一个房子
if n == 1:
return nums[0]
# 如果只有两个房子 (n=2), 因为不能同时偷,所以只能偷金额较大的那一个
# 这个情况其实会被下面的主要逻辑覆盖,但也可以单独处理
# if n == 2:
# return max(nums[0], nums[1])
# --------------------
# --- 主要逻辑:分解为两个线性问题 ---
# 因为第一个和最后一个房子不能同时偷,问题分解为:
# 1. 偷窃范围是 [0, n-2] (不偷最后一个房子)
# 2. 偷窃范围是 [1, n-1] (不偷第一个房子)
# 取这两种情况的最大值即可。
# 情况 1: 考虑房子 0 到 n-2 (不包括最后一个房子 nums[n-1])
# 创建切片 nums[0:n-1] (注意:切片不包括索引 n-1 的元素)
nums_with_first = nums[0 : n-1]
# 情况 2: 考虑房子 1 到 n-1 (不包括第一个房子 nums[0])
# 创建切片 nums[1:n] (注意:切片从索引 1 开始)
nums_without_first = nums[1 : n]
# 分别调用辅助函数 rob0 计算两种情况下的最大金额
# self.rob0(nums_with_first) 计算情况 1 的最大值
# self.rob0(nums_without_first) 计算情况 2 的最大值
result = max(self.rob0(nums_with_first), self.rob0(nums_without_first))
# 返回两种情况中的最大值作为最终结果
return result