力扣第213题 打家劫舍|| c++ 附Java代码 将回环转线性 动态规划
题目
中等
相关标签
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
示例 1:
输入:nums = [2,3,2] 输出:3 解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:
输入:nums = [1,2,3,1] 输出:4 解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。
示例 3:
输入:nums = [1,2,3] 输出:3
思路和解题方法
首先rob
函数接受一个整数数组nums
,表示每个房屋中的金钱数量。首先判断数组的长度,如果为空,则返回0;如果只有一个房屋,则直接返回该房屋的金额。- 然后,通过调用
robmoney
函数分别计算两种情况下的最大金额。robmoney
函数接受一个整数数组nums
、起始位置start
和结束位置end
,用于计算从第start
个房屋到第end
个房屋之间的最大金额。- 在
robmoney
函数中,首先判断如果只有一个房屋,则直接返回该房屋的金额。然后创建一个大小与nums
相同的dp数组,用于保存计算过程中的结果。将第一个房屋的金额存储在dp[start]
中,将第二个房屋的金额选择偷或不偷的较大者存储在dp[start+1]
中。- 接下来,从第三个房屋开始遍历,计算每个房屋处的最大金额。对于每个房屋,可以选择偷或不偷。如果选择偷,则最大金额为前两个房屋的最大金额加上当前房屋的金额;如果选择不偷,则最大金额为前一个房屋的最大金额。取两者中较大的金额作为当前位置的最大金额,并将其存储在
dp
数组中。- 最后,返回
dp[end]
作为最大金额的结果。
复杂度
时间复杂度:
O(n)
时间复杂度为O(n),其中n是房屋的数量。这是因为在该函数中,我们需要调用
robmoney
函数两次,每次计算的时间复杂度都是O(n),因此总时间复杂度为O(n)。
空间复杂度
O(n)
时间复杂度也为O(n),其中n是从
start
到end
之间的房屋数量。在该函数中,我们使用了一个dp数组来存储每个位置处的最大金额,因此空间复杂度为O(n)。
c++ 代码
class Solution {
public:
int rob(vector<int>& nums) {
if(nums.size()==0) return 0;
if(nums.size() ==1) return nums[0];
int ans1 = robmoney(nums,0,nums.size() - 2); // 第一次计算从0到n-2的最大金额
int ans2 = robmoney(nums,1,nums.size() - 1); // 第二次计算从1到n-1的最大金额
return max(ans1,ans2); // 返回两次计算中的较大者
}
int robmoney(vector<int> &nums,int start,int end)
{
if(end == start) return nums[start]; // 只有一个房屋时直接返回该房屋的金额
vector<int> dp(nums.size()); // 定义dp数组
dp[start] = nums[start]; // 初始化dp数组
dp[start+1] = max(nums[start],nums[start+1]);
for(int i = start+2;i<=end;i++)
{
dp[i] = max(dp[i-2]+nums[i],dp[i-1]); // 计算当前位置的最大金额
}
return dp[end]; // 返回dp数组的最后一个元素作为结果
}
};
Java代码
rob
函数接受一个整数数组nums
,表示每个房屋中的金钱数量。首先进行一些预处理,如果nums
为null或长度为0,则返回0。如果nums
只有一个元素,则直接返回该元素的值。- 然后,通过调用
robAction
函数分别计算两种情况下的最大金额。robAction
函数接受一个整数数组nums
、起始位置start
和结束位置end
,用于计算从第start
个房屋到第end
个房屋之间的最大金额。- 在
robAction
函数中,我们使用三个变量x、y和z来记录计算过程中的最大金额。开始时,它们都初始化为0。然后,从第start
个房屋开始遍历到第end-1
个房屋。- 在每一次遍历中,我们使用y暂存z的值,以便下一次计算。然后,我们通过比较y和x加上当前房屋的金额nums[i]的和,来更新z的值。最后,我们将y的值更新为z之前的值,以备下一次计算使用。
- 最终,返回z作为最大金额的结果。
- 这段代码的时间复杂度为O(n),其中n是房屋的数量。因为在
robAction
函数中,我们只进行了一次遍历,并对每个房屋进行常数时间的计算。所以整体的时间复杂度为O(n)。空间复杂度为O(1),因为我们只使用了三个额外的变量来保存计算过程中的值。
class Solution {
public int rob(int[] nums) { // rob函数接收一个整数数组nums作为参数
if (nums == null || nums.length == 0) // 如果数组为空,直接返回0
return 0;
int len = nums.length; // 获取数组长度
if (len == 1) // 如果数组只包含一个元素,则直接返回该元素的值
return nums[0];
return Math.max(robAction(nums, 0, len - 1), robAction(nums, 1, len)); // 计算两种情况下的最大金额并返回较大者
}
int robAction(int[] nums, int start, int end) { // robAction函数用于计算从start到end之间的最大金额
int x = 0, y = 0, z = 0; // 初始化三个变量x、y、z
for (int i = start; i < end; i++) { // 遍历从start到end之间的房屋
y = z; // 将上一个房屋的最大金额存储在y中
z = Math.max(y, x + nums[i]); // 计算当前房屋的最大金额,并将结果存储在z中
x = y; // 将上一个房屋的最大金额存储在x中
}
return z; // 返回最后一个房屋处的最大金额作为结果
}
}
觉得有用的话可以点点赞,支持一下。
如果愿意的话关注一下。会对你有更多的帮助。
每天都会不定时更新哦 >人< 。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)