leetcode挑战4新手讲解向,打家劫舍闭环问题

8 篇文章 0 订阅
7 篇文章 0 订阅

原题

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。

给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed. All houses at this place are arranged in a circle. That means the first house is the neighbor of the last one. Meanwhile, adjacent houses have a security system connected, and it will automatically contact the police if two adjacent houses were broken into on the same night.

Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.

示例 1:

输入:nums = [2,3,2]
输出:3
解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
示例 2:

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

输入:nums = [0]
输出:0
 

提示:

1 <= nums.length <= 100
0 <= nums[i] <= 1000

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

答案

class Solution {
 public int rob(int[] nums) {
        //长度为1直接返回值
        if(nums.length == 1){
            return nums[0];
        }else{
            int[] nums1 = new int[nums.length - 1];
            int[] nums2 = new int[nums.length - 1];
            for(int i = 0; i < nums.length - 1; ++i){
                nums1[i] = nums[i];
                nums2[i] = nums[nums.length - 1 - i];
            }
            //返回两者的最大值
            return Math.max(singleTreatment(nums1), singleTreatment(nums2));
        }
    }
    public int singleTreatment(int[] nums){
        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 - 2] + nums[i], dp[i - 1]);
        }
        return dp[nums.length - 1];
    }
   
}

解析

  1. 因为前后闭环的原因,在分成两个问题来求解,一个是从0到length-1,一个是从1到length。
  2. 如果nums为1或者2时很容易就得到结果,就是取最大值即可
  3. 当长度大于3时,需要从左往右遍历,从第三个数开始,取走到前i-2间房子可以取得的最大收益加上抢这间房的收益,和走到前i-1间房可以取得的最大值但这间房就不能抢了。这两个值做一个对比来得到走到这间房时可以获得的最大收益。
  4. 直到走到最后倒数最后一间就知道到最大值了

说人话

这是一道经典的动态规划问题。
要理解这道题需要简单的抽象化问题。

  1. 要决定抢不抢一个房子,很简单看最大的收益,
  2. 先从第0间开始,毫无疑问此时最大收益就是抢了,就是dp[0]了,
  3. 第1间,毫无疑问最大收益毫无疑问就是第0和第1的收益取最大得到的值,dp[1]
  4. 第2间,此时就要考虑了,如果抢了这一间,则第1间则不能取到最大收益了(因为抢了第2间就不能抢第1间了),那么抢了第2间的收益就应该时dp[0]+第2间的钱,不抢的收益则是dp[1],这两个取最大则是dp[2]了
  5. 同理可以一直类推到倒数最后一间,即dp[length-1]就是走到最后取到的最大值了
  6. 难点在于,你要清楚,你抢不抢这间房,其实只和上间房和上上间房抢不抢有关系而已。
  7. 简单点换个说法,假设老板要你上7天班,每天给你发不定额的钱假设为(1,3,2,4,6,4),但规定不能连续上两天班。
  8. 那么从第一天开始,上班可以拿到1,
  9. 第二天上班即第一天就不能上了,最大拿到的就是3,
  10. 第3天上了则是第二天就不能上了,只能拿到第一天的收益1,2+1刚好和3相等,即其实第一天上班和第三天上班和第二天上班的收益都是3,
  11. 然后就是第4天的选择了,这里我们肯定知道要选第二天的3加上今天的上班的4才是最大收益。所以这里你仔细思考,其实和第一天已经没关系了,第一天的钱已经被第二天和第三天的收益包括了

个人理解,欢迎指导

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值