1

House Robber I

You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

DP

复杂度

O(N) 时间 O(N) 空间

思路

dp[i] = max{dp[i - 1], dp[i - 2] + value[i]}
抢不抢第i间房子,取决于第i-1间房子抢了没抢:
1 如果第i-1间抢了,那当前(第i间房)就绝不能抢; dp[i] = dp[i - 1]
2 如果第i-1间没抢,那当前(第i间房)可抢可不抢; dp[i] = max(value[i] + dp[i - 2], dp[i - 1])
合并两个得到上面的状态转移方程。

注意

房子的value都是正整数
可以用滚动数组把空间复杂度降低到O(1)

代码

public class Solution {
    public int rob(int[] nums) {
        if (nums.length == 0)
            return 0;
        int[] dp = new int[nums.length + 1];
        dp[0] = 0;
        dp[1] = nums[0];
        for (int i = 2; i < nums.length + 1; i++) {
            dp[i] = Math.max(nums[i - 1] + dp[i - 2], dp[i - 1]);
        }
        return dp[nums.length];
    }
}

House Robber II

Note: This is an extension of House Robber.

After robbing those houses on that street, the thief has found himself a new place for his thievery so that he will not get too much attention. This time, all houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, the security system for these houses remain the same as for those in the previous street.

Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.

DP

复杂度

O(N) 时间 O(N) 空间

思路

这回房子连成环了,言下之意是:抢第一个就不能抢最后一个,不抢第一个抢不抢最后一个随意
两种情况:
1.抢第一间(第二间必须不抢,第三间随意),不抢最后一间(倒数第二间随意)
2.不抢第一间(第二间随意),最后一间抢不抢随意(倒数第二间也随意)
这两种情况分别dp,找最大的就ok了

注意

不抢第一个的情况下,最后一个并不一定要抢,也可以不抢

代码

public class Solution {
    public int rob(int[] nums) {
        int n = nums.length;
        if (n == 0)
            return 0;
        if (n == 1)
            return nums[0];
        int[] dpRobFirst = new int[n + 1];
        int[] dpNotRobFirst = new int[n + 1];
        dpRobFirst[1] = nums[0];
        dpRobFirst[2] = dpRobFirst[1];
        dpNotRobFirst[1] = 0;
        dpNotRobFirst[2] = nums[1];
        for (int i = 3; i <= n - 1; i++) {
            dpRobFirst[i] = Math.max(dpRobFirst[i - 1], nums[i - 1] + dpRobFirst[i - 2]);
            dpNotRobFirst[i] = Math.max(dpNotRobFirst[i - 1], nums[i - 1] + dpNotRobFirst[i - 2]);
        }
        dpRobFirst[n] = dpRobFirst[n - 1];
        dpNotRobFirst[n] = Math.max(dpNotRobFirst[n - 1], nums[n - 1] + dpNotRobFirst[n - 2]);
        return Math.max(dpRobFirst[n], dpNotRobFirst[n]);
    }
}

House Robber III

The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night.

Determine the maximum amount of money the thief can rob tonight without alerting the police.

分治

复杂度

O(N) 时间 O(N) 空间

思路

树,用分治:
对于当前节点,两种情况:

  1. 抢当前节点,左右子节点必须都不能抢

  2. 不抢当前节点,左右子节点分别可抢可不抢,共四种情况

注意

不抢当前节点有四种情况,别漏

代码

定义一个返回类型,对于每个节点,返回一个Status,里面包括抢/不抢当前节点分别可以得到的最大value

class Status {
    int rob;
    int notRob;
    Status(int rob, int notRob) {
        this.rob = rob;
        this.notRob = notRob;
    }
}

主程序

public class Solution {
    public int rob(TreeNode root) {
        Status s = helper(root);
        return Math.max(s.rob, s.notRob);
    }
    //given the root node, tell me the maximum money of both rob and not rob current node.
    public Status helper(TreeNode root) {
        if (root == null)
            return new Status(0, 0);
        if (root.left == null && root.right == null)
            return new Status(root.val, 0);
        Status left = helper(root.left);
        Status right = helper(root.right);
        int robCur = root.val + left.notRob + right.notRob;
        int notRobCur = maxOfFour(left.rob + right.rob, 
                                  left.rob + right.notRob, 
                                  left.notRob + right.rob, 
                                  right.notRob + left.notRob);
        return new Status(robCur, notRobCur);
    }
    public int maxOfFour(int a, int b, int c, int d){
        int max = Math.max(a, b);
        max = Math.max(max, c);
        max = Math.max(max, d);
        return max;
    }
}

liuqi627
364 声望100 粉丝