首页 > 技术文章 > House Robber

NickyYe 2015-04-26 22:31 原文

https://leetcode.com/problems/house-robber/

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,所以印象也比较深刻。

我们定义子状态dp[i]为,从左往右偷到i这家时候,能偷的最大金额。那么dp[i]的值有两种可能,

1. 如果偷了i - 1,那么 i 这家就不能偷了,这时候dp[i]=dp[i - 1]。

2. 如果i-1不偷,那么i这家可以偷,加上前面已经偷的最大金额dp[i - 2]。所以dp[i] = dp[i - 2] + nums[i]。

于是,dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i])。

有了这个状态转换公式,dp就可以写出来了。一维的,线性时间。

public class Solution {
    public int rob(int[] nums) {
        if(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 - 1], dp[i - 2] + nums[i]);
        }
        return dp[nums.length - 1];
    }
}

当然,我们知道一般这种一维的dp都不要用一个数组来保存结果。可以观察到上面其实只用到i,i-1和i-2三个结果。可以只维护三个变量,然后迭代更新。空间降为O(1)。

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

 

推荐阅读