1. LeetCode 198.打家劫舍
题目链接:https://leetcode.cn/problems/house-robber/
文章链接:https://programmercarl.com/0198.打家劫舍.html#算法公开课
视频链接:https://www.bilibili.com/video/BV1Te411N7SX
思路:
递推公式:
第j个房间偷还是不偷
偷:dp[j-2]+nums[i]
不偷:dp[j-1]
dp[j]=Math.max(dp[j-2]+nums[j],dp[j-1])
class Solution {
public int rob(int[] nums) {
if (nums.length==1) {
return nums[0];
}
//1.定义dp数组
//dp[j]表示下标j以内的房间(包括j)所能偷窃的最大值
int[] dp = new int[nums.length];
//2.递推公式
//第j个房间偷还是不偷
//偷:dp[j-2]+nums[i]
//不偷:dp[j-1]
//dp[j]=Math.max(dp[j-2]+nums[j],dp[j-1])
//3.初始化
dp[0] = nums[0];
dp[1] = Math.max(nums[0],nums[1]);
//4.遍历顺序
for (int j=2;j<nums.length;j++) {
dp[j] = Math.max(dp[j-2]+nums[j],dp[j-1]);
}
return dp[nums.length-1];
}
}
2. LeetCode 213.打家劫舍II
题目链接:https://leetcode.cn/problems/house-robber-ii/
文章链接:https://programmercarl.com/0213.打家劫舍II.html
视频链接:https://www.bilibili.com/video/BV1oM411B7xq
思路:
关键是如何理解环形。
对于一个数组,成环的话主要有如下三种情况:
情况一:不考虑首尾;
情况二:考虑首,不考虑尾;
情况三:考虑尾,不考虑首。
而情况二、情况三包含情况一。因此只需考虑情况二、情况三即可。
解法:
class Solution {
public int rob(int[] nums) {
if (nums.length==1) {
return nums[0];
}
int head = process(nums,0,nums.length-2);
int tail = process(nums,1,nums.length-1);
return Math.max(head,tail);
}
public int process(int[] nums,int start,int end) {
if (start == end) {
return nums[start];
}
//1.定义dp数组 dp[i]表示i下标以内偷窃的最高金额
int[] dp = new int[nums.length];
//2.递推公式
//dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i])
//3.初始化
dp[start] = nums[start];
dp[start+1] = Math.max(nums[start],nums[start+1]);
//4.遍历顺序
for (int i=start+2;i<=end;i++) {
dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[end];
}
}
3. LeetCode 337.打家劫舍III
题目链接:https://leetcode.cn/problems/house-robber-iii/
文章链接:https://programmercarl.com/0337.打家劫舍III.html#思路
视频链接:https://www.bilibili.com/video/BV1H24y1Q7sY
思路:
本题关键:后序遍历+返回值是一个二维数组,其中0索引值是当前节点偷的最大金额,1索引值是当前节点不偷的最大金额。注意:这里的最大金额,是以该节点为根节点的树的在不触发警报的前提下的最大金额和。
当前节点可以偷或者不偷;
若偷,则左右子节点就不能偷,获取左右节点的不偷的最大金额之和+本节点金额
若不偷,则左右子节点可以偷或者不偷,分别获取左右子节点偷或者不偷的最大金额之和。
由于是深度优先搜索遍历,且利用了左右子节点的返回值,则使用后序遍历。
返回值数组就是dp数组。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public int rob(TreeNode root) {
int[] res = process(root);
return Math.max(res[0],res[1]);
}
public int[] process(TreeNode root) {
// 终止条件
if (root == null) return new int[]{0,0};
// 左
int[] left = process(root.left);
// 右
int[] right = process(root.right);
// 中
// 当前节点偷还是不偷
// 偷
int rob = left[1] + right[1] + root.val;
// 不偷
int norob = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);
return new int[]{rob,norob};
}
}