原题链接: 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);
}
}