LeetCode213.打家劫舍II

112 阅读2分钟

「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战

题目

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。

示例 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 = [0] 输出:0

提示:

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 1000

解题思路

本题重点在于房屋是环状排列,意味着第一个房子和最后一个房子中只能选择一个偷窃(或者都不偷窃)。这样可以分为三种情况:

  1. 首尾两个房子都不抢
  2. 抢第一间房子,不抢最后一间
  3. 抢最后一间房子,不抢第一间

image.png 我们可以发现无论如何情况2,3偷盗区间都比1要大,也就是情况2,3偷盗金额一定大于等于1的,因此,可以本题简化为在 198.打家劫舍 中的两个单排问题,在两种单排金额中取最大值,即可得到本地的解

动态规划做法:

定义 dp[i] 表示考虑抢劫 nums[0...i] 所能获得的最大收益(注意这里是闭区间) 由于不可以同时偷相邻的房屋,所以在当前位置为 i 房屋可盗窃的最大值要么就是 i-1 房屋可盗窃的最大值,要么就是 i-2 房屋可盗窃的最大值加上当前房屋的值,二者之间取最大值 所以状态转移方程为:dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]) 本题中对比 198 题不同在于封装动态规划函数,分别传入剔除第一个和最后一个房间的数组,求最大值即可 时间复杂度为 O(n)

var rob = function(nums) {
    if (nums.length < 2) return nums[0];
    var subrob = function(nums) {
        if (nums.length < 2) return nums[0];
        let temp = Math.max(nums[0],nums[1])
        let dp = [nums[0], temp];
        for (let i = 2; i < nums.length; i++) {
            dp[i] = Math.max(dp[i - 1],dp[i - 2] + nums[i]);
        }
        return dp[nums.length - 1]
    };
    return Math.max(subrob(nums.slice(1)),subrob(nums.slice(0,nums.length - 1)))
};