题干
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
示例 1:
输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
复制代码
思路:动态规划
这道题的基本大意就是将nums设置环形,那我们就需要考虑第一个元素与最后一个元素,因为它们两者不能连续。
因此我们需要分两种情况,就是有第一个元素与没有第一个元素的情况。我们可以将这两种情况拆解成两个基础打家劫舍问题。保证首位不重合。这就需要我们留意dp数组的起始值了。
代码实现:
执行用时:96 ms, 在所有 JavaScript 提交中击败了21.01%的用户
内存消耗:40.6 MB, 在所有 JavaScript 提交中击败了5.02%的用户
var rob = function (nums) {
/*
将打家劫舍第一个版本拆解成了两个不同的结构
*/
if (nums.length == 1) {
return nums[0]
}
//分两种情况,就是使前后元素不相遇的情况,注意参数值
let oneVersion = doRob(nums, 0, nums.length - 1)
let twoVersion = doRob(nums, 1, nums.length)
return oneVersion > twoVersion ? oneVersion : twoVersion
};
/*
这里的操作与打家劫舍相同,只是初始值不同
*/
function doRob(nums, begin, end) {
let dp = [];
dp[0] = nums[begin]
dp[1] = nums[begin + 1]>nums[begin]?nums[begin+1]:nums[begin]
//拆解后dp数组只有两个元素的情况
if (end - begin == 2) {
return dp[0] > dp[1] ? dp[0] : dp[1]
}
//我这里循环dp数组给其加元素,所以长度就是end-begin,你也可以遍历nums数组,就是需要注意我们的dp数组应该与nums数组的长度一致。
for (let i =2; i < end-begin; i++) {
dp[i] = Math.max(nums[i+begin] + dp[i - 2], dp[i - 1])
}
//最后返回dp数组的最后一位
return dp[end-begin - 1]
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END