打家劫舍

kitten 发布于 2024-06-11 213 次阅读


你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

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

在我们有了0-1背包问题的解题思路后,就可以大概分析出该如何处理这个问题。这里还是精确的稍微说一下。

看到题目我们大概明确,就是在一个一维数组n中取一些数相加取最大值,这些数字不能是相邻的。像这种求最大值的问题我们都叫求最优解的问题。最优解的问题都有一个特点:整体的情况非常之多,会显得整体非常复杂。这个时候我们就不要盯着整体,要找到一张简单的局部。

我们定义一个dp[i],表示这个数组n中从下标0开始到下标i这个位置,这个范围之内找到的最大求和的结果。那么在i等于最大下标的时候,dp[i]所对应的就是我们本题所求的解。

那么dp[i]如何求得呢?它其实可以表示为:是否要n[i],要的话n[i-1]就不可以选,此时dp[i]=n[i]+dp[i-2]。不要的话n[i-1]就可以选,此时dp[i]=dp[i-1]。

下面是代码

public class HouseRobber {
    public int rob(int[] nums) {
        if(nums == null || nums.length == 0) {
            return 0;
        }
        
        int n = nums.length;
        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = nums[0];
        
        for(int i = 2; i <= n; i++) {
            dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i - 1]);
        }
        
        return dp[n];
    }

    public static void main(String[] args) {
        HouseRobber houseRobber = new HouseRobber();
        int[] nums = {2,7,9,3,1};
        System.out.println(houseRobber.rob(nums)); // Output: 12
    }
}