1、数组类型
你面前房子的索引就是状态,抢和不抢就是选择。
public int rob(int[] nums) {
int n = nums.length;
int[] dp = new int[n+2]; //dp[i]表示从i到最后一个房子最多能盗取的金额
for(int i=n-1;i>=0;i--){
dp[i] = Math.max(dp[i+1], nums[i]+dp[i+2]);
}
return dp[0];
}
2、环形
首先,首尾房间不能同时被抢,那么只可能有三种不同情况:要么都不被抢;要么第一间房子被抢最后一间不抢;要么最后一间房子被抢第一间不抢。
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n>=2)
return Math.max(dp(nums,0,n-2), dp(nums,1,n-1));
else
return nums[0];
}
public int dp(int[] nums, int start, int end){
int n = nums.length;
int[] dp = new int[n+2];
for(int i=end;i>=start;i--){
dp[i] = Math.max(dp[i+1], nums[i]+dp[i+2]);
}
return dp[start];
}
}
3、二叉树类型
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
class Solution {
public int rob(TreeNode root) {
return Math.max(dp(root)[0], dp(root)[1]);
}
public int[] dp(TreeNode root){//返回一个大小为2的数组arr,arr[0]表示不抢root得到的最大收益, arr[1]表示抢root得到的最大收益
if(root==null){
return new int[]{0,0};
}
int[] left = dp(root.left); //左子树根节点抢left[0]或者不抢left[1]
int[] right = dp(root.right);//右子树根节点抢right[0]或者不抢right[1]
int rob = root.val + left[0] + right[0];//若抢了根节点,则左右子数根节点都不能抢
int not_rob = Math.max(left[0],left[1]) + Math.max(right[0],right[1]);//若不抢根节点,则判断左右子树抢不抢根节点哪种情况划算
return new int[]{not_rob, rob};
}
}