leetcode 力扣 198 打家劫舍

64 阅读1分钟

又是抽象的dp

一开始误以为是跳着偷,隔一间偷一间,被自己蠢到了

动态转移方程为:
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1])

dp[i - 2] + nums[i] 表示偷第i家,再加上前i - 2家以来积累的赃款

dp[i - 1] 表示不偷第i家,表示前i - 1家以来积累的赃款

边界条件
dp[0] = nums[0] 只有一家可偷

dp[1] = Math.max(nums[0], nums[1]) 只有两家可偷,偷最多的

下图中偷和不偷[0, 1]都初始化为7

绿色表示偷,黄色表示不偷,蓝色表示当前可以偷最多钱的路径。

👇 偷33加上i - 2中钱最多的,3 + 7 = 10
不偷3i - 1中钱最多的,7

1.jpeg

👇偷99加上i - 2中钱最多的,9 + 7 = 16
不偷9i - 1中钱最多的,10

2.jpeg

👇偷22加上i - 2中钱最多的,2 + 10 = 12
不偷2i - 1中钱最多的,16

3.jpeg

public int rob(int[] nums) {
        int len = nums.length;
        if (len == 1) {
            return nums[0];
        }

        int[] dp = new int[len];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);

        for (int i = 2; i < len; i++) {
            dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
        }

        return dp[len - 1];
    }