#198 House Robber

Description

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

Examples

Example 1:

Input: nums = [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
Total amount you can rob = 1 + 3 = 4.

Example 2:

Input: nums = [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
Total amount you can rob = 2 + 9 + 1 = 12.

Constraints:

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

思路

这是一道动态规划题,所以问题的关键就在于划分子问题和确定状态转移方程

题目的限定是:一个小偷不能偷两个相邻的住户,所以在现在所处的第 t t t 个街区,会有两种情况出现

  • 要么他不进行偷窃,那到 t t t 为止,他能得到和 t − 1 t-1 t1 一样多的钱
  • 要么他进行偷窃,那除了能得到第 t t t 个街区的钱之外,还能得到和 t − 2 t-2 t2 街区一样多的钱

当然可能会有这个问题:为什么不用考虑 t − 3 t-3 t3 乃至 t − i t-i ti 街区的情况呢?
那是因为 t − 2 t-2 t2 街区的到手钱情况并不是描述偷窃了 t − 2 t-2 t2手中资金的情况,而是说明到达 t − 2 t-2 t2 为止,手中持有资金最多的情况。这种情况下,小偷可能进行了偷窃,也可能没有。并且 t − 2 t-2 t2 t t t 之间至少相隔了一个 t − 1 t-1 t1 让小偷确保不被抓住,因此可以直接使用该场景。

有了定义之后,就可以给出状态转移方程,假设第 t t t 户人家拥有 f ( t ) f(t) f(t) 的资金,小偷在到达 t t t 社区时,手中可以持有的最高金额为 g ( t ) g(t) g(t)

  • 首先是初始化
    g ( 0 ) = f ( 0 ) g ( 1 ) = max ⁡ ( f ( 1 ) , f ( 0 ) ) \begin{aligned} g(0) &= f(0)\\ g(1) &=\max({f(1), f(0)}) \end{aligned} g(0)g(1)=f(0)=max(f(1),f(0))
  • 从第三户人家开始,就依据上面提到的两种情况更新当前情况
    g ( t ) = max ⁡ ( g ( t − 1 ) , f ( t ) + g ( t − 2 ) ) g(t)=\max({g(t-1),f(t)+g(t-2)}) g(t)=max(g(t1),f(t)+g(t2))

最后返回 f ( n − 1 ) f(n-1) f(n1) 就是最优解啦

代码

class Solution {
    public int rob(int[] nums) {
        if(nums.length == 1)
            return nums[0];
        if(nums.length == 2){
            return Math.max(nums[0], nums[1]);
        }
        
        int[] answer = new int[nums.length];
        answer[0] = nums[0];
        answer[1] = Math.max(nums[0], nums[1]);
        
        for(int i = 2; i < nums.length; i++){
            answer[i] = Math.max(answer[i - 2] + nums[i], answer[i - 1]);
        }
        
        return answer[nums.length - 1];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值