【问题描述】[简单]
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。示例 1:输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。偷窃到的最高金额 = 1 + 3 = 4 。
【解答思路】
1. 动态规划
第 1 步:设计状态
int[] dp = new int[len + 1];
第 2 步:状态转移方程
dp[n] = MAX( dp[n-1], dp[n-2] + num )
第 3 步:考虑初始化
dp[0] = 0;
dp[1] = nums[0];
第 4 步:考虑输出
dp[len]
第 5 步:考虑是否可以状态压缩
方法2
时间复杂度:O(N) 空间复杂度:O(N)
class Solution {public int rob(int[] nums) {int len = nums.length;if(len == 0)return 0;int[] dp = new int[len + 1];dp[0] = 0;dp[1] = nums[0];for(int i = 2; i <= len; i++) {dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i-1]);}return dp[len];}
}
与上面方法略有不同
class Solution {public int rob(int[] nums) {int n = nums.length;// 处理边界条件。if (n == 0) {return 0;}if (n == 1) {return nums[0];}// 定义dp数组,按照状态转移方程递推。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];}
}
2. 动态规划压缩空间
参照着 dp[i] = max(dp[i - 1], dp[i - 2] + nums[i]) 这个方程来写,
用 a 表示 i - 2,b 表示 i - 1,
因此上面的方程变成了dp[i] = max(b, a + nums[i]),
然后下一轮循环的时候:
i - 1 就变成了i - 2,因此现在需要把 b 赋值给 a;
i 就变成了 i - 1,因此现在需要把 dp[i] 赋值给 b。
时间复杂度:O(N) 空间复杂度:O(1)
class Solution {public int rob(int[] nums) {int a = 0, b = 0;for (int i = 0; i < nums.length; i++) {int c = Math.max(b, a + nums[i]);a = b;b = c;}return b;}
}
【总结】
1.dp数组设置多一个 在前面添加后者后面添加
int[] dp = new int[len + 1];
2.动态规划流程
第 1 步:设计状态
第 2 步:状态转移方程
第 3 步:考虑初始化
第 4 步:考虑输出
第 5 步:考虑是否可以状态压缩
3.动态规划做多了 第一次自己写了出来,可惜初始化没有想全面
转载链接:https://leetcode-cn.com/problems/house-robber/solution/liang-ge-yue-0ji-chu-cong-an-mo-shi-zhuan-xing-zi-/