题目链接:198.打家劫舍
思路:
第一步:确定 dp 数组所表示的含义,dp[i] 表示包括下标为 i 的房屋,最高可以偷窃的金额为 dp[i]。
第二步:确定递推公式,决定 dp[i] 的值的问题在于第 i 个房间偷还是不偷;
如果偷窃第 i 个房间,则 dp[i] = dp[i - 2] + nums[i];
如果不偷窃第 i 个房间,则 dp[i] = dp[i - 1];
对于上面两种情况取其最大值,所以 dp 数组的递推公式为
d p [ i ] = M a t h . m a x ( d p [ i − 1 ] , d p [ i − 2 ] + n u m s [ i ] ) dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]) dp[i]=Math.max(dp[i−1],dp[i−2]+nums[i])
第三步:初始化,从递推公式可以得出,需要初始化 dp[0] 和 dp[1];
所以,dp[0] = nums[0]
;对于 dp[1] , dp[1] = Math.max(nums[0], nums[1])
;
第四步:遍历,从i = 2 开始进行遍历,遍历整个 nums 数组。
代码:
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0){
return 0;
}
if (nums.length == 1){
return nums[0];
}
int[] dp = new int[nums.length];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < nums.length; i++){
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[nums.length - 1];
}
}
题目链接:213.打家劫舍II
思路:
本题思路与LeetCode198.打家劫舍思路相同。
不同之处:第一个房屋和最后一个房屋是相连的,即所有的房屋组成了一个环。所以,将情况进行细分为两种情况。
分别对上面两种情况进行分析,从中取出最大值。
代码:
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0){
return 0;
}
if (nums.length == 1){
return nums[0];
}
int result1 = robRange(nums, 0, nums.length - 2);
int result2 = robRange(nums, 1, nums.length - 1);
return Math.max(result1, result2);
}
private int robRange(int[] nums, int start, int end) {
if (end == start){
return nums[start];
}
int[] dp = new int[nums.length];
dp[start] = nums[start];
dp[start + 1] = Math.max(nums[start], nums[start + 1]);
for (int i = start + 2; i <= end; i++){
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[end];
}
}
题目链接:337.打家劫舍III
思路:
本题涉及二叉树的知识,对二叉树的递归三部曲进行分析。
第一步:确定递归函数的参数和返回值(以及 dp 数组的所表示的含义)
定义一个递归函数为 int[] dp = robTree(TreeNode root)
。
dp 数组的下标所表示的含义,dp[0] 表示不偷窃该节点所获得的最高金钱,dp[1] 表示偷窃该节点所获得的最高金钱。
第二步:确定终止条件,当遇到空节点时,进行终止并返回。
第三步,确定遍历顺序,本题采用的是后序遍历。因为通过递归函数的返回值去做下一步的计算。
首先通过在左节点进行递归操作,获取偷或不偷左节点的金钱;
通过在右节点进行递归操作,获取偷或不偷右节点的金钱。
第四步:确定单层递归逻辑,分为两种情况,
res[0] = root.val + left[0] + right[0]
;res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1])
。代码:
class Solution {
public int rob(TreeNode root) {
int[] dp = robTree(root);
return Math.max(dp[0], dp[1]);
}
private int[] robTree(TreeNode root) {
int[] res = new int[2];
if (root == null){
return res;
}
int[] left = robTree(root.left);
int[] right = robTree(root.right);
res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
res[1] = root.val + left[0] + right[0];
return res;
}
}