打家劫舍系列上篇

68 阅读2分钟

一、打家劫舍(力扣198)

此题的动态规划有两种思路:

1、思路一:

参考309. 最佳买卖股票时机含冷冻期-力扣 ,我也写的有题解:

买卖股票系列(力扣121、122、123、188、309、714) Java动态规划

房屋只有两种状态:被偷 和 没被偷

那么我们用dp数组来记录第i间房屋时的最大金额,dp[i][0] 记录被偷的情况,dp[i][1]记录没被偷的情况。

dp[i][0]表示被偷,那么前一间必然没有被偷,当前值就是前一间没有被偷的情况下的金额+当前金额,则dp[i][0] = dp[i-1][1] + nums[i]

dp[i][1]表示没被偷,那么前一间可能被偷,也可能没被偷,当前值就是这两种情况中较大的那个,则dp[i][1] = max{ dp[i-1][0] , dp[i][1] }

最后取dp[len-1][0]和dp[len-1][1]的较大值即可。考虑到当前房屋值只与前一间房屋有关,则可以用变量来代替dp数组,就成了下面的代码。

在买卖股票的题解(上面的链接)中有此方法更详细的讲解和推导过程,感兴趣的朋友可以去看一下。

class Solution {
    public int rob(int[] nums) {
        int a = nums[0];
        int b = 0;
        for(int i=1; i<nums.length; i++) {
            int tempA = a;
            int tempB = b;
            a = tempB + nums[i];
            b = Math.max(tempA, tempB);
        }
        return Math.max(a, b);
    }
}

2、思路二

对于第k间房屋,只有两种情况:被偷 和 不被偷

如果被偷,当前金额为k-2间房屋的金额+当前金额

如果不被偷,当前金额为k-1间房屋金额

这间房屋的金额就是两个值中较大的那个,所以得到递推公式:

dp[i]=max(dp[i−2]+nums[i],dp[i−1])

class Solution {
 
    static int max = 0;
 
    public int rob(int[] nums) {
 
        if(nums.length==1){
            return nums[0];
        }
    
        int c = nums[0];
        int b = Math.max(nums[0], nums[1]);
        int a = nums[0];
        for(int i=2; i<nums.length; i++){
            a = Math.max(b, (c+nums[i]));
            c = b;
            b = a;
        }
        return Math.max(a, b);
    }
}