[Java恶补day60] 整理模板·考点十三【动态规划】
【问题描述】
【思考步骤】⭐
step1· 构造回溯
①入参、返回值
②递归到哪里
③递归边界、递归入口
step2· 改为记忆化搜索
step3· 1:1翻译为递推
198. 打家劫舍【模板题】
你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400
知识点:
数组、动态规划
【步骤1:回溯】
- 当前操作?枚举第iii个房子选/不选
- 子问题?从前iii个房子中得到的最大金额和
- 下一个子问题?
a. 不选:从前i−1i-1i−1个房子中得到的最大金额和
b. 选:从前i−2i-2i−2个房子中得到的最大金额和 - 状态转移方差:dfs[i]=max(dfs[i−1],dfs[i−2]+nums[i])dfs[i] = max(dfs[i-1], dfs[i-2]+nums[i])dfs[i]=max(dfs[i−1],dfs[i−2]+nums[i]),表示从nums[0]nums[0]nums[0]到nums[i]nums[i]nums[i]最多能偷多少
【步骤2:记忆化搜索】
6. 记忆化搜索 = 递归搜索 + 保存计算结果
7. 记忆化搜索:自顶向下计算
8. 保存计算结果:把递归的计算结果保存下来,下次递归到相同入参时,就直接返回之前保存的结果
【步骤3:递推】
9. 递推 = 自底向上计算
10. 翻译为递推的方法:
a. dfs → f数组
b. 递归 → 循环
c. 递归边界 → 数组初始值
代码(记忆化搜索):
时间复杂度:O(n)O(n)O(n)。
空间复杂度:O(n)O(n)O(n)。
class Solution {public int rob(int[] nums) {// 初始化数组,元素均为-1,记录已计算过的int n = nums.length;int[] memo = new int[n];Arrays.fill(memo, -1);//从最后一个房子开始搜索return dfs(n - 1, nums, memo);}// dfs[i] = 从nums[0]到nums[i]最多能偷多少private int dfs(int i, int[] nums, int[] memo) {//递归边界if (i < 0) {return 0;}//若之前计算过if (memo[i] != -1) {return memo[i];}//记忆化,并返回答案int notChoose = dfs(i - 1, nums, memo);int choose = dfs(i - 2, nums, memo) + nums[i];memo[i] = Math.max(notChoose, choose);return memo[i];}
}
代码(递推):
时间复杂度:O(n)O(n)O(n)。
空间复杂度:O(n)O(n)O(n)。
class Solution {public int rob(int[] nums) {int n = nums.length;int[] f = new int[n + 2]; //不让下标为负数//递归→循环for (int i = 0; i < n; i++) {f[i + 2] = Math.max(f[i + 1], f[i] + nums[i]);}//从最后一个房子开始搜索return f[n + 1];}
}
代码(空间优化):
时间复杂度:O(n)O(n)O(n)。
空间复杂度:O(1)O(1)O(1)。
class Solution {public int rob(int[] nums) {int f0 = 0;int f1 = 0;for (int x : nums) {int newF = Math.max(f1, f0 + x);f0 = f1;f1 = newF;}return f1;}
}
参考:
1、灵神题解
知识点:
解:
时间复杂度:O()O()O()。
空间复杂度:O()O()O()。
参考:
1、灵神题解
知识点:
解:
时间复杂度:O()O()O()。
空间复杂度:O()O()O()。
参考:
1、灵神题解