这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战
leetcode213:打家劫舍2
前文
本文为菜鸟的刷题记录,仅用作笔记使用,并非最佳解决方案。
题目信息
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
解题思路分析
解法1
与直线排布打家劫舍相对比,本题目最大的不同,便是房屋排布成环状。类似于直线型打家劫舍问题的思路,需要对前面的节点进行记录。而最大的不同,是在节点数据计算时,要对于是否采用了首节点进行区分。本思路主要是对于采用首节点和不采用首节点同时进行存储。计算两类打家劫舍的结果。如果不采用首节点,则与常规直线型打家劫舍思路相同,进行对应的加和及比较即可。而对于采用了首节点的偷窃方式,要注意首尾节点不能够进行连续偷窃。当首节点被偷窃时,尾节点要进行特殊判断,不能进行偷窃。最后对两种不同的偷窃方案进行比较即可。至此,题目分析解决完毕。变量采用固定数目变量存储,优化空间复杂度。
public int rob(int[] nums) {
int[] pos = new int[6];
if(nums.length == 0){
return 0;
}else if(nums.length == 1){
return nums[0];
}else if(nums.length == 2){
return Math.max(nums[0],nums[1]);
}else if(nums.length == 3){
return Math.max(Math.max(nums[0],nums[1]), nums[2]);
}
// 初始化信息包含是否使用了初始字段
pos[4] = 0;
pos[5] = 0;
pos[2] = nums[0];
pos[3] = nums[1];
pos[0] = Math.max(nums[0] + nums[2],nums[1]);
pos[1] = nums[1] > nums[2] ? nums[1]:nums[2];
// 规划方程
for (int i = 3; i < nums.length; i++) {
int max;
if(i != nums.length-1){
max = Math.max(Math.max(pos[3] + nums[i],pos[2] + nums[i]),Math.max(pos[0],pos[1]));
}else{
max = Math.max(Math.max(pos[3] + nums[i],pos[2]),Math.max(pos[0],pos[1]));
}
int maxWithoutZero = Math.max(pos[3]+nums[i],pos[1]);
pos[5] = pos[3];
pos[4] = pos[2];
pos[3] = pos[1];
pos[2] = pos[0];
pos[1] = maxWithoutZero;
pos[0] = max;
}
return Math.max(pos[0],pos[1]);
}
复杂度分析
- 时间复杂度 o(n)
- 空间复杂度 o(1)
后记
- 千古兴亡多少事?悠悠。不尽长江滚滚流。