LeetCode-198-打家劫舍

动态规划

Posted by 刘知安 on 2020-08-21
文章目录
  1. 1. 题目描述
  2. 2. 思路
  3. 3. 代码
  • 4. 相似题
  • 1. 题目描述

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

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

    示例 1:

    1
    2
    3
    4
    输入:[1,2,3,1]
    输出:4
    解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
      偷窃到的最高金额 = 1 + 3 = 4

    示例 2:

    1
    2
    3
    4
    输入:[2,7,9,3,1]
    输出:12
    解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
      偷窃到的最高金额 = 2 + 9 + 1 = 12

    提示:

    • 0 <= nums.length <= 100
    • 0 <= nums[i] <= 400

    2. 思路

    🌰我们用示例1来举例,我们假设小偷从左往右开始偷东西,没到一户门口,他可以选择偷/不偷,各房屋的财产分布情况如下:

    1.png

    • 首先,我们假设小偷来到了最后一户人家,前面的偷/不偷决定均已完成,我们也已经知道前面各个决策对应的最大收益,用dp[]来记录,dp[i]表示偷完前i户的最大收益;

    • 其次,我们考虑最后一次决策:

      • 如果选择偷第3户(0-based index)人家,那么肯定不能偷第2户人家,于是我们需要知dp[1],则dp[1]+nums[3]为选择偷第3户的收益;

      • 如果选择不偷第3户(0-based index)人家,那收益就是dp[2]了。

        取上述两种情况的最大值即可。

    • 最后,就将上述的2种决策分别运用于前面的人家即可。注意,为了方便处理,我们将dp数组设计为1-based index的,并将dp[0]初始化为0, 将dp[1]初始化为nums[0]。从而得到下述的动态转移方程:

    3. 代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    class Solution {
    public int rob(int[] nums) {
    if(nums.length<=0)
    return 0;

    int[] dp=new int[nums.length+1];
    dp[0]=0;
    dp[1]=nums[0]; // 只有一家肯定是要偷的
    for (int i=2;i<=nums.length;i++)
    {
    dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i-1]); // 不偷/偷 第i家
    }

    return dp[nums.length];
    }
    }

    4. 相似题