[LeetCode] 198. House Robber

原题链接: https://leetcode.com/problems/house-robber/

House Robber 专题相关题目

198. House Robber
213. House Robber II
337. House Robber III

1. 题目介绍

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 system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

你是一个专业的强盗,计划去房屋里面抢劫。每个房子都有一定数量的钱存在。相邻的房屋有连接的安全系统,如果两个相邻的房子在同一个晚上被抢劫,房屋将自动报警。

给出一个数组,里面的数都是非负数,代表第i个房子里面的钱数,求在不报警的情况下,能拿到的最多的钱数。

也就是,给出一个数组,求数组中不相邻数的和最大是多少?

Example 1:

Input: [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: [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.

2. 解题思路

动态规划法

设置一个数组dp[] ,假设盗贼从第1间房子依次向后拿钱。dp[ i ]存放走到第 i 间房子时能够拿走的最多钱数。dp[ i ]的值就是 第i-1个房子能够拿到的最大钱数,和当前房子能够拿到的钱数+从0到i-2间房子能拿到的钱数的最大值。

状态转移方程如下:

dp[i] = max( dp[i-1] , Max + nums[i] ) 

其中Max是指从dp[0]到dp[i-2]中最大的数。

为什么不是下面的方程呢?

dp[i] = max( dp[i-1] , dp[i-2] + nums[i] ) 

因为dp[i-2]未必是最大的。比如例子[2,1,1,2]。如果按照 dp[i-2] + nums[i]来算,是无法得到正确结果的。

实现代码

class Solution {
   public int rob(int[] nums) {
        int length = nums.length;
        if(length ==0 ) {
        	return 0;
        }
        if(length ==1) {
        	return nums[0];
        }

        int [] dp = new int[length];
        int Max = nums[0];
        
        dp[0] = nums[0];
        dp[1] =  nums[1];
        for(int i = 2;i<length;i++) {
            if(dp[i-2] > Max){
                Max = dp[i-2];
            }
        	dp[i] = Math.max(dp[i-1] , Max + nums[i] ) ;
        }
        return Math.max(dp[length-1],dp[length-2]);
    }
}

进一步改进

上述动态规划方法中,每一次的循环其实只用到了dp[ i-2 ]和dp[ i-1 ],因此可以用两个整数存储dp[i-2]和dp[i-1]的数值,这样就不用设置数组了。

class Solution {
   public int rob(int[] nums) {
        int length = nums.length;
        
        if(length ==0 ) {
        	return 0;
        }
        if(length ==1) {
        	return nums[0];
        }

        int a,b,c;
        int Max = 0;
        
        a = nums[0];
        b = nums[1];
        for(int i = 2;i<length;i++) {
        	if(a > Max){
                Max = a;
            }
        	c = Math.max( b  , Max + nums[i] ) ;
        	
        	a = b;
        	b = c;
        	
        }
        return Math.max(a,b);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值