打家劫舍

本文介绍了如何使用动态规划解决LeetCode上的经典问题——House Robber,即在不触发警报的情况下,计算所能偷窃到的最高金额。通过分析问题本质,得出状态转移方程,并提供了两种实现方式:一种使用额外数组存储状态,另一种通过滚动数组优化空间复杂度。最后,对两种方法的时间和空间复杂度进行了分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目介绍

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

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

在这里插入图片描述

分析

由于不能偷窃连续的房屋,我们自然想到,隔一个偷一间显然是一个不错的选择。那是不是,直接计算所有奇数项的和,以及所有偶数项的和,取最大值就可以了呢?并没有这么简单。例如,如果是[2,7,1,3,9],很明显,偷2,1,9或者7,3都不是最佳选择,偷7,9才是。
这里的关键是,对于三个连续的房屋2,7,1,由于跟后面的9都隔开了,所以我们可以选择偷2,1,也可以直接选择偷7。这就需要分情况讨论了。所以我们发现,从最后往前倒推,最后一间屋n,有偷和不偷两种选择:

  • 如果偷,那么前一间屋n-1一定没有偷,我们考虑n-2之前的最优选择,加上n就可以了;
  • 如果不偷,那么n-1之前的最优选择,就是当前的最优选择。

所以,这明显是一个动态规划的问题。

动态规划实现

我们可以将前n个房屋能偷到的最大金额,保存到状态数组dp。前i个房屋能够偷到的最大金额,就是dp[i]。

可以得到状态转移方程:
在这里插入图片描述
代码演示如下:

public class HouseRobber {
    // 动态规划
    public int rob(int[] nums) {
        int n = nums.length;
        if (nums == null || n == 0) return 0;

        int[] dp = new int[n + 1];
        dp[0] = 0;
        dp[1] = nums[0];
        // 遍历状态,依次转移
        for (int i = 2; i <= n; i++){
            dp[i] = Math.max( dp[i-1], dp[i-2] + nums[i-1] );    
        }
        return dp[n];
    }
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度。只需要对数组遍历一次。
  • 空间复杂度:O(n)。使用数组dp存储状态,长度为n+1。

空间优化

上述方法使用了数组存储结果。
我们通过状态方程可以发现,每间房屋的最高总金额,只和该房屋的前两间房屋的最高总金额相关。因此只要存储之前两间房屋的最高金额就可以了。

代码如下:

// 动态规划空间优化
public int rob(int[] nums) {
    int n = nums.length;
    if (nums == null || n == 0) return 0;
    int pre2 = 0;
    int pre1 = nums[0];
    // 遍历状态,依次转移
    for (int i = 1; i < n; i++){
        int curr = Math.max(pre1, pre2 + nums[i]);
        pre2 = pre1;
        pre1 = curr;
    }
    return pre1; 
}

复杂度分析

  • 时间复杂度:O(n),其中 n 是数组长度。只需要对数组遍历一次。
  • 空间复杂度:O(1)。使用滚动数组,只存储前两间房屋的最高总金额,而不需要存储整个数组的结果,因此空间复杂度是 O(1)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值