算法:打家劫舍213. House Robber II

Posted 架构师易筋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了算法:打家劫舍213. House Robber II相关的知识,希望对你有一定的参考价值。

213. House Robber II

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

Example 1:

Input: nums = [2,3,2]
Output: 3
Explanation: You cannot rob house 1 (money = 2) and then rob house 3 (money = 2), because they are adjacent houses.

Example 2:

Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

Example 3:

Input: nums = [1,2,3]
Output: 3

Constraints:

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

拆分为两个子集解法

由于这个问题是 House Robber 的后续问题,我们可以假设我们已经有了解决更简单问题的方法,即给定 1 排房子,我们知道如何抢劫他们。所以我们已经有了这样一个辅助函数。我们对其进行了一些修改以抢劫给定范围的房屋。

private int rob(int[] num, int lo, int hi) {
    int include = 0, exclude = 0;
    for (int j = lo; j <= hi; j++) {
        int i = include, e = exclude;
        include = e + num[j];
        exclude = Math.max(e, i);
    }
    return Math.max(include, exclude);
}

现在的问题是如何抢劫一排圆形房屋。像更简单的问题一样解决起来有点复杂。因为在更简单的问题中,是否抢夺num[lo]完全是我们的选择。但是,现在受到num[hi]是否被抢劫的限制。

但是,由于我们已经对更简单的问题有了很好的解决方案。我们不想扔掉它。那么,我们如何将这个问题简化为更简单的问题。其实,从i家没被抢的逻辑延伸,你可以自由选择是否抢i+1家,你可以假设房子没有被抢来打破这个圈子。

例如,1 -> 2 -> 3 -> 1 变成 2 -> 3 如果 1 没有被抢劫。

由于每栋房子要么被抢要么没有被抢,至少有一半的房子没有被抢,所以解决方案就是连续房子的两种情况中较大的一个,即房子我没有被抢,打破圆圈,解决它,或者房子我+ 1 没有被抢劫。因此,下面的解决方案。为了更简单的编码,我选择了 i = n 和 i + 1 = 0。但是,您可以选择两个连续的。

public int rob(int[] nums) {
    if (nums.length == 1) return nums[0];
    return Math.max(rob(nums, 0, nums.length - 2), rob(nums, 1, nums.length - 1));
}

完整代码

class Solution {
    public int rob(int[] nums) {
        if (nums.length == 1) return nums[0];
        return Math.max(rob(nums, 0, nums.length - 2), rob(nums, 1, nums.length - 1));
    }
    
    private int rob(int[] nums, int l, int r) {
        int include = 0, exclude = 0;
        for (; l <= r; l++) {
            int i = include, e = exclude;
            include = exclude + nums[l];
            exclude = Math.max(i, e);
        }
        
        return Math.max(include, exclude);
    }
}

参考

https://leetcode.com/problems/house-robber-ii/discuss/59934/Simple-AC-solution-in-Java-in-O(n)-with-explanation

以上是关于算法:打家劫舍213. House Robber II的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 213. House Robber II

1线性DP 213. 打家劫舍 II

213. House Robber II

leetcode 198. House Robber 打家劫舍(中等)

动态规划 - 213. House Robber II

LeetCode 213. House Robber II