198.打家劫舍

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_leetcode

class Solution {
public int rob(int[] nums) {
if(nums.length == 1) return nums[0];
int[] dp = new int[nums.length];
dp[0] = nums[0];
// 2 1 1 2 这里设置初始值需要注意
dp[1] = Math.max(nums[0],nums[1]);
for(int i = 2;i < nums.length;i++){
dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i]);
}
return dp[nums.length - 1];
}
}

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_Math_02

213.打家劫舍II

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_leetcode_03

class Solution {
public int rob(int[] nums) {
if(nums.length == 1) return nums[0];
return Math.max(f(nums,0,nums.length - 1),f(nums,1,nums.length));
}
int f(int[] nums,int start,int end){
int x = 0,y = 0,z = 0;
for(int i = start;i < end; i++){
y = z;
z = Math.max(y,x + nums[i]);
x = y;
}
return z;
}
}

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_leetcode_04

337.打家劫舍 III

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_i++_05


最开始想用层次遍历,发现不行,代码如下:

/**
* 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) {
Queue<TreeNode> queue = new LinkedList<>();
queue.add(root);
int a = 0;
int b = 0;
int i = 1;
while(!queue.isEmpty()){
int len = queue.size();
int result = 0;
while(len > 0){
TreeNode temp = queue.poll();
result += temp.val;
len--;
if(temp.left != null) queue.add(temp.left);
if(temp.right != null) queue.add(temp.right);
}
if(i % 2 == 1){
a += result;
}else{
b += result;
}
result = 0;
i++;
}
return Math.max(a,b);
}
}

这种情况就不符合

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_Math_06

普通递归偷

/**
* 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) {
if(root == null) return 0;
int money = root.val;
if(root.left != null){
money += rob(root.left.left) + rob(root.left.right);
}
if(root.right != null){
money += rob(root.right.left) + rob(root.right.right);
}
return Math.max(money,rob(root.left) + rob(root.right));
}

}


可以使用一个map把计算过的结果保存一下,这样如果计算过孙子了,那么计算孩子的时候可以复用孙子节点的结果。

/**
* 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 {
Map<TreeNode,Integer> map;
public int rob(TreeNode root) {
map = new HashMap<>();
return rob1(root);
}
int rob1(TreeNode root){
if(root == null) return 0;
if(map.containsKey(root)) return map.get(root);
int money = root.val;
if(root.left != null){
money += rob1(root.left.left) + rob1(root.left.right);
}
if(root.right != null){
money += rob1(root.right.left) + rob1(root.right.right);
}
int money2 = rob1(root.left) + rob1(root.right);
map.put(root,Math.max(money,money2));
return Math.max(money,money2);
}

}

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_Math_07

这里我们要求一个节点 偷与不偷的两个状态所得到的金钱,那么返回值就是一个长度为2的数组。
res[0]表示没偷当前节点,res[0] = Math.max(left[0],left[1]) + Math.max(right[0],right[1]); 也就是左右两节点有没有被偷过无所谓,取偷过或者没偷过的最大值即可。
res[1]表示偷了当前节点,res[1] = root.val + left[0] + right[0] 也就是左右孩子节点没被偷过的值加上当前被偷的值就是盗取的金额。

/**
* 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 = RobAction(root);
return Math.max(res[0],res[1]);
}
int[] RobAction(TreeNode root){
int[] res = new int[2];
if(root == null){
return res;
}
int[] left = RobAction(root.left);
int[] right = RobAction(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;
}
}

198.打家劫舍 213.打家劫舍II 337.打家劫舍 III_动态规划_08