今日心情:你能做成你想做的任何事!
题目描述:
LeetCode 198. 打家劫舍
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
解题代码:
class Solution {
public int rob(int[] nums) {
//特殊情况判断
if(nums == null){return 0;}
//nums 长度为1 直接返回 数本身
int len = nums.length;
if(len == 1){return nums[0];}
//创建动态数组
int[] dp = new int[len];
// 确定base case
dp[0] = nums[0];
dp[1] = Math.max(dp[0],nums[1]);
//转移方程
for(int i = 2;i < len;i++){
dp[i] = Math.max(dp[i-2]+nums[i],dp[i-1]);
}
return dp[len-1];
}
}
解题思路:
本来想的是用两个for遍历一个从0位置开始到 倒数第二个数,然后计算一个从1开始到倒数第一个数。然而不是geeral 的解决方法,比如说有4个数的时候,偷第一个和最后一个的总和为最大的情况就不好使了。本来想消除这些条件加一些限制,但是尝试无果之后,直接看的题解,接下来是题解的方法+自己的理解。
(1)首先空数组判断:如果数组为空,直接返回0
(2)获取有几家可以抢:int len = nums.length;
- 如果数组的长度为1: 说明只有1家可以rob,直接返回nums[0]
- 如果数组长度大于2:进行动态规划求可以rob的最大金额
(3)创建动态数组dp记录能抢的最大金额
- 确定 base case :
dp[0] = nums[0]; 起始情况只有一家:能抢的最大金额也只能是nums[0]
dp[1] = Math.max(dp[0],nums[1]); 现在有两家可以抢了,但是连续抢2家会触发报警,所以最大能抢的是两家中的最大值。
dp[2...len-1] 的情况需要通过确定动态转移方程来找到最大可以rob的金额
- 确定动态转移方程
在 dp[i] 的情况( i >= 2 的时候),要么当前 i 可以 rob, 则其可以 rob 的最大金额为 dp[i-2] + nums[i], 否则当前 i 不可rob ,则当前最大可以rob 的金额就是上一个可以rob的最大金额数 dp[i-1]。
(4)最后dp[len-1]就是在整个能抢的范围内的最大金额数,返回return dp[len-1]。