【动态规划】Leetcode 198. 打家劫舍【中等】

打家劫舍

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

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

示例 1:

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

解题思路

这是一个经典的动态规划问题,可以使用动态规划来解决。定义一个数组 dp, 其中 dp[i] 表示偷窃前 i 个房屋能够获得的最高金额。

  • 1、对于每间房屋,小偷有两种选择:偷当前房屋或者不偷当前房屋。
  • 2、如果选择偷第 i 个房屋,则不能偷第 i-1 个房屋,因此偷窃金额为 nums[i] 加上前 i-2 个房屋能够获得的最高金额 dp[i-2]。
  • 3、如果选择不偷第 i 个房屋,则偷窃金额为前 i-1 个房屋能够获得的最高金额 dp[i-1]。
    因此,动态规划方程如下:
  •  dp[i] = max(dp[i-1], dp[i-2] + nums[i]),其中 2 <= i < n
    
    边界条件为:
  •   dp[0] = nums[0],只有一个房屋时能够获得的最高金额为该房屋金额
    
  •  dp[1] = max(nums[0], nums[1]),只有两个房屋时能够获得的最高金额为其中金额较大的房屋
    
  • 4、最终返回 dp[n-1] 即可得到最大的偷窃金额。

Java实现

public class HouseRobber {
    public int rob(int[] nums) {
        if (nums == null || nums.length == 0) return 0;
        if (nums.length == 1) return nums[0];
        
        int n = nums.length;
        int[] dp = new int[n];
        dp[0] = nums[0];
        dp[1] = Math.max(nums[0], nums[1]);
        
        for (int i = 2; i < n; i++) {
            dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i]);
        }
        
        return dp[n-1];
    }

    public static void main(String[] args) {
        HouseRobber robber = new HouseRobber();
        int[] nums = {1, 2, 3, 1};
        System.out.println("Maximum amount stolen: " + robber.rob(nums)); // Output: 4
    }
}

时间空间复杂度

  • 时间复杂度:遍历一次数组,时间复杂度为O(n),其中n为房屋的数量。

  • 空间复杂度:使用了长度为n的数组dp,空间复杂度为O(n)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值