LeetCde#198: House Robber

Description

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.

Example

Input: [1,2,3,1]
Output: 4
Explanation: Rob house 1 (money = 1) and then rob house 3 (money = 3).
             Total amount you can rob = 1 + 3 = 4.
Input: [2,7,9,3,1]
Output: 12
Explanation: Rob house 1 (money = 2), rob house 3 (money = 9) and rob house 5 (money = 1).
             Total amount you can rob = 2 + 9 + 1 = 12.

Solution

解动态规划题目一般有三种递进的思路:

  1. 找到递归关系(或者说是状态转移方程)
  2. 使用递归
  3. 使用递归+备忘录
  4. 使用循环+备忘录
  5. 使用循环

再来看看这道题。如果抢劫当前房子的话,那么上一个房子就不能被抢,此时的解为上上个房子的解加上当前房子的值;如果不抢劫当前房子的话,此时的解就为上个房子的解。因此,我们可以很容易的得到状态转移方程为f(n) = Max(f(n-2) + curr, f(n-1))

递归

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

递归+备忘录

使用递归会产生很多重复的计算,因此可以使用一个备忘录数组来保存已计算出的结果,避免重复递归。

public class Solution2 {
	int[] memo;	
	
    public int rob(int[] nums) {
    	memo = new int[nums.length];
    	Arrays.fill(memo, -1);
        return rob(nums, nums.length-1);
    }
    
    private int rob(int[] nums, int i) {
    	if(i < 0)
    		return 0;
    	if(memo[i] >= 0)
    		return memo[i];
    	int res = Math.max(rob(nums, i-2)+nums[i], rob(nums, i-1));
    	memo[i] = res;
    	return res;
    }
}

循环+备忘录

递归操作可以使用循环替代。

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

循环

不使用备忘录,而用两个变量来保存前两个状态的解。

public class Solution4 {
    public int rob(int[] nums) {
        if(nums.length == 0) return 0;
        if(nums.length == 1) return nums[0];
        int prev1 = nums[0];
        int prev2 = Math.max(nums[1], prev1);
        for(int i = 2; i < nums.length; i++) {
        	int curr = Math.max(prev1+nums[i], prev2);
        	prev1 = prev2;
        	prev2 = curr;
        }
        return prev2;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值