力扣刷题笔记《动态规划篇》→ 198. 打家劫舍

225 阅读1分钟

这是我参与8月更文挑战的第8天,活动详情查看:8月更文挑战

题目

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

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

示例

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

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

提示

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

解题思路

题目限制了相邻的两间房不能连续偷窃,那么这里我们先做一个边界判断

  • 当房间数k小于等于2时:
    • k == 1:直接返回结果
    • k == 2:两间取其中价值最高的
  • 当房间数大于2时:
    • 偷窃第k间房,则k-1的房间不能偷:最大值为k + (k - 2)的总金额

    • 不偷窃第k间房:最大值为k - 1的总金额

    • 状态转移:dp[i] = Math.max(nums[i] + dp[i - 2], dp[i - 1])

image.png

代码实现

class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        // yes表示偷窃,no表示不偷窃
        // 由于这里只需要保留 k-1 的总金额,以及 k-2 的总金额,所以采用变量进行优化
        int yes = nums[0], no = 0, tmp;

        for(int i = 1; i < n; ++i){
            // 相当于 dp[i] = Math.max(nums[i] + dp[i - 2], dp[i - 1])
            tmp = Math.max(nums[i] + no, yes);
            no = yes;
            yes = tmp;
        }

        return yes;
    }
}

复杂度分析

  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1)

最后

文章有写的不好的地方,请大佬们不吝赐教,错误是最能让人成长的,愿我与大佬间的距离逐渐缩短!

如果觉得文章对你有帮助,请 点赞、收藏、关注、评论 一键四连支持,你的支持就是我创作最大的动力!!!

题目出处:leetcode-cn.com/problems/ho…