力扣
1. 物品:每个房间的现金,背包:金额;01背包
2. dp数组及其下标含义:dp[i]表示到房间i时所偷窃的最高金额为dp[i];
3. 递推公式:dp[i] = Math.max(dp[i-1], dp[i-2]+nums[i]);
4. 初始化:dp[0] = nums[0],dp[1] = Math.max(nums[0],nums[1]);【注意,题目中说nums.length>=1,当nums长度为1时直接返回】
5. 遍历顺序:dp[i]的值依赖dp[i-1]和dp[i-2],因此从前往后遍历;
class Solution {
public int rob(int[] nums) {
int len = nums.length;
if (len==1) return nums[0];
int[] dp = new int[len];
dp[0] = nums[0];
dp[1] = Math.max(dp[0], nums[1]);
for (int i=2; i
力扣
1. 基本同上;
2. 区别:分为从i=0开始偷,偷到i=nums.length-1,和从i=1开始偷,偷到i=nums.length-2这两种情况;返回两种情况下金额更大的那个;
class Solution {
public int rob(int[] nums) {
int len = nums.length;
if (len == 1) return nums[0];
return Math.max(robAction(nums, 0, len - 1), robAction(nums, 1, len));
}
public int robAction(int[] nums, int start, int end) {
int x = 0, y = 0, z = 0;//相当于只维护dp[i],dp[i-1]和dp[i-2]
for (int i=start; i
力扣
1. 首先思考遍历方式:前中后序(深度优先搜索)还是层序遍历(广度优先搜索)。本题一定是后序遍历,因为需要通过递归函数的返回值做下一步计算。
2. 如果抢了当前节点,那么两个孩子就不能动;如果没抢当前节点,就「考虑」抢左右孩子。
3. 确定递归函数的参数和返回值:需要使用一个长度为2的数组,记录当前节点偷与不偷所得到的最大金钱,因此返回值为长度为2的int[]【即dp数组,dp[0]记录不偷该节点所得到的的最大金钱,dp[1]记录偷该节点所得到的的最大金钱。】
4. 终止条件:当遇到空节点时,返回 new int[]{0,0}。
5. 遍历顺序:后序遍历;递归左节点,用left[]记录左节点偷和不偷的情况。递归右节点,用right[]记录右节点偷和不偷的情况。
6. 单层递归的逻辑:若果偷当前节点,那么左右孩子就不能偷,因此dp[1] = cur.val + left[0] + right[0];如果不偷当前节点,那么左右孩子就可以偷,至于到底偷不偷,那一定是选一个最大的,因此dp[0] = Math.max(left[0], left[1]) + max(right[0], right[1]);最后头节点返回偷和不偷两种情况中金钱最多的那一个;
class Solution {
public int rob(TreeNode root) {
int[] res = robAction(root);
return Math.max(res[0],res[1]);
}
public int[] robAction(TreeNode root){
int[] dp = new int[2];
if(root==null) return dp;
int[] left = robAction(root.left);
int[] right = robAction(root.right);
dp[0] = Math.max(left[0],left[1])+Math.max(right[0],right[1]);
dp[1] = root.val+left[0]+right[0];
return dp;
}
}
class Solution {
Map memo = new HashMap<>();
public int rob(TreeNode root) {
return robAction(root);
}
public int robAction(TreeNode root){
if(root==null) return 0;
if(memo.containsKey(root)) return memo.get(root);
int money = root.val;
if(root.left!=null){
money+=robAction(root.left.left)+robAction(root.left.right);
}
if(root.right!=null){
money+=robAction(root.right.left)+robAction(root.right.right);
}
int res = Math.max(money,robAction(root.left)+robAction(root.right));
memo.put(root,res);
return res;
}
}