算法题 打家劫舍(动态规划)

题目:

你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。

给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。

 

示例 1:

输入:[1,2,3,1]
输出:4
解释:偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
     偷窃到的最高金额 = 1 + 3 = 4 。

示例 2:

输入:[2,7,9,3,1]
输出:12
解释:偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
     偷窃到的最高金额 = 2 + 9 + 1 = 12 。

 

提示:

    0 <= nums.length <= 100
    0 <= nums[i] <= 400

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/house-robber
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

分析:

如果没有可以偷的房屋,则直接返回0。

如果只有一家可以偷的房屋,则直接返回即可。

如果只有两家可以偷的房屋,则对比收益进行返回。

现在以示例一为例:[1,2,3,1]。

假设只有前三家房屋,那么如何计算最高收益?最高收益有两种情况,要么包含盗窃下标为2的房屋,要么则不包含。

假设包含的话,则不能盗取下标为1的房屋,否则触发警报。

假设不包含的话,则最高收益应等于盗取下标为1的房屋及它之前的房屋的最高收益。

根据这个思路可以总结出状态转移方程,进而用代码实现,在解决这种问题的时候,可以将下次运算需要的值先记录下来,避免重复解决子问题。

代码:

 

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

 

posted @ 2020-07-18 11:26  无心大魔王  阅读(410)  评论(0编辑  收藏  举报