算法初探LeetCode-5.打家劫舍

118 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第5天,点击查看活动详情

LeetCode198:打家劫舍

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

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

示例 1

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

示例 2

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

提示:

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

思路分析

首先可以分析出这是一道 动态规划 算法的题。按照动态规划的解题步骤:

  • 第一点:根据题意会有设定一个动态数组DP[n], 其中下标为i的房间,最多可以偷窃DP[i];
  • 第二点:关键点是下标为i的房间是否盗窃?结合示例来,若确定盗窃i标号,那么可以偷到DP[i] = DP[i-2] + 标号i房间的钱;若不盗窃i号房,那么DP[i]就是(i-2)号和(i-1)号的最大值;
  • 第三点由上一点的推断得出初始两个房间可以偷到的钱 DP[0],DP[1]
    最后通过遍历得出结果。

nums[]就是所有盗窃房间存有的钱组成的数组,DP为设定的动态数组,最关键是推断出第一家DP[0]和第二家DP[1]的可偷取值。

该题最主要是运用动态规划算法来分析解决。

算法代码

public int rob(int[] nums) {
    if (nums == null || nums.length == 0) return 0;
    int len = nums.length;                                            
    if(len == 0) return 0;                                            
    int[] DP = new int[len + 1];                                      
    DP[0] = 0;          //选择偷第一家,可偷最大值
    DP[1] = nums[0];    //选择偷第二家,累加可偷最大值                                  
    for(int i = 2; i <= len; i++) {                                   
        DP[i] = Math.max(DP[i-1], DP[i-2] + nums[i-1]);  //选择偷第 i 家,累加可偷最大值 
    }                                                                 
    return DP[len];                                                   
}

结果

Snipaste_2022-10-07_23-14-23.png

算法复杂度

  • 空间复杂度:O(n)O(n)
  • 时间复杂度:O(n2)O(n^2)

掘金(JUEJIN)一起进步,一起成长!