Leetcode----213打家劫舍||+198打家劫舍|

今天的每日一题是《打家劫舍||》,先找到《打家劫舍|》做一下,熟悉一下题目。

打家劫舍|

在这里插入图片描述

在这里插入图片描述

解题思路

简单的动态规划问题,找到规律就非常简单,但是题目的范围给挖了一个坑,需要注意规避(数组的长度是从0开始的,所以要对数组长度为0的情况进行处理,虽然我没尝试不处理会怎么样,但是也应该注意到这个问题)。

  1. 因为不能偷连续的两个房子的财物,所以对于数组长度length=1和2的情况进行处理,分别返回nums[0]和nums[0]、nums[1]中的较大值;
  2. 对于length>2的情况,设置dp[0]和dp[1]分别等于nums[0]和nums[1],下面开始进行动态规划;因为为了取得更多的钱,在不触发警报(不偷连续两家)的前提下,每次应该偷钱最多的家庭,所以每次应该加上除了邻近的上一户之外,累计金额最高的几户家庭,所以使用max存储当前累计金额的最大值,每户自己的钱和max进行相加,即是当前最大的累计金额;
  3. 因为max是当前家庭i之前的i-2户的累计金额的最大值,所以在输出结果时,需要比较max(即前i-2户的累计最大值)、dp[length-2](前i-1户的累计最大值)、dp[length-1](前i户的累计最大值)中的最大值,即为能偷到钱的最大累计值。

代码

class Solution {
    public int rob(int[] nums) {
        int length = nums.length;
        if(length == 0)
            return 0;
        if(length == 1)
            return nums[0];
        if(length == 2)
        {
            return nums[0]> nums[1]?nums[0]:nums[1];
        }
        int dp[] = new int[length];
        dp[0] = nums[0];
        dp[1] = nums[1];
        int max = dp[0];

        for(int i=2;i<length;i++)
        {            
            max = Math.max(max, dp[i-2]);
            dp[i] = nums[i] + max;
        }
        return Math.max(Math.max(max, dp[length-2]), dp[length-1]);
    }
}

打家劫舍||

image.png在这里插入图片描述

解题思路

emmmmm,思考问题还是不严谨,期间出了很多小的问题,第三次提交才通过。。。
与198打家劫舍|的问题相比,该题添加了一个环形排列的新特点,因此选择哪个点作为动态规划的起始点显得至关重要,所以我没选。。。哈哈哈。直接全部做一次起始点,找到其中的最大结果就可以了。

  1. 对于数组长度为1和2的情况进行单独处理;
  2. 使数组的每个节点都作为起始节点,然后分别进行动态规划,因为最后一个节点的值与第一个节点有关,但是因为本方法是循环处理的,所以直接不用对每次的最后一个节点进行处理;
  3. 在每次动态规划后,记录本次的最大值cur_max,与max进行对比,存储较大的值到max中,最后返回max即可。

具体的详见代码中注释

代码

class Solution {
    public int rob(int[] nums) {
        int length = nums.length;
        if(length == 1)
            return nums[0];
        if(length == 2)
        {
            return nums[0]> nums[1]?nums[0]:nums[1];
        }

        int max,cur_max,i;
        int count = 0;
        max=-1;

        while(count<length)
        {
            i=count;
            int dp[] = new int[length];
            dp[0] = nums[i];
            i = (i+1)%length;
            dp[1] = nums[i];

            cur_max = dp[0];
            i = (i+1)%length;
            int j=2;//之所以设置j是因为无论数组内容如何循环处理,dp的索引值始终是一致的,最开始没注意这一点,而是直接利用i的值,错了很久。。。
            while(i!=(count-1+length)%length)
            {
                cur_max = Math.max(cur_max, dp[j-2]);//因为不能偷邻近的两家,所以cur_max存储的是前j-2家的累计最大值
                dp[j] = nums[i] + cur_max;
                i = (i+1)%length;//因为是循环处理,所以要加上length并进行取余
                j++;
            }

            cur_max = Math.max(cur_max, dp[length-2]);//因为不用管最后一个节点,所以与198打家劫舍|的代码Math.max(Math.max(max, dp[length-2]), dp[length-1])不同
            max = Math.max(max,cur_max);//保存每次循环的最大值

            count++;
        }
        return max;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值