213. House Robber II

题目描述

每个房子有一定的钱

  1. 条件 不能偷相邻房子的钱
  2. 条件 第一个房子和最后一个房子相邻,围成一个圆形,也就是不能同时偷第一个房子和最后一个房子的钱

解题思路

如果抢劫第一家,则不可以抢最后一家;否则,可以抢最后一家。因此,这个问题就转化成为了两趟动规,可以复用 “House Robber” 的代码。

对第一个房子到倒数第二个房子进行动态规划, 对第二个房子到最后一个房子进行动态规划,求两种情况下的最大值即可。

###动态规划
本次题目中的动态规划,每个位置处的能盗取的金额值最大值,只与前面两个位置有关,
dp[i] = max(dp[i-1]+nums[i], dp[i-1])

空间简化,使用两个变量记录前后两个位置的最大值,到最后一个位置时,取两个变量中的最大值即可

代码(自己的想法)

先按照House Robber 1中的常规动态规划算法处理到倒数第二个元素,得到一个最大值,然后判断最大值中是否包括第一个元素的情况,然后单独处理最后一个结果,
这种情况,就是考虑不全,还不如在开始的时候就考虑是否包括第一或最后一个元素

代码(Java)

public  int solution_2(int []nums){
        if(nums.length==1) return nums[0];
        //两个元素的情况
        if(nums.length==2) return Math.max(nums[0],nums[1]);
        //三个元素的情况
        return Math.max(robber(nums, 0,nums.length-1),robber(nums, 1,nums.length));

    }
    private int  robber(int[] nums, int begin, int end){
        //边界条件的处理情况
        if (nums == null || begin >= end) return 0;
        //只有三个元素的情况下
        if(end-begin==1) return Math.max(nums[begin],nums[end]);
        //四个元素以上的情况
        int even,odd;
        if(begin%2==0) {
            even = nums[begin];
            odd = Math.max(nums[begin+1],nums[begin]);
        }
        else
        {
            odd = nums[begin];
            even = Math.max(nums[begin+1],nums[begin]);
        }
        for(int i=begin+2;i<end;++i) {
            if (i % 2 == 0) {
                even = Math.max(odd,even+nums[i]);
            }
            else
                odd = Math.max(even,odd+nums[i]);
        }
        return Math.max(even,odd);

    }

代码(Java)

对上述的代码进行简化处理,逻辑等情况

public int rob(int[] nums) {
    if (nums.length == 1) return nums[0];
    return Math.max(rob(nums, 0, nums.length - 2), rob(nums, 1, nums.length - 1));
}

private int rob(int[] num, int lo, int hi) {
    int include = 0, exclude = 0;
    for (int j = lo; j <= hi; j++) {
        int i = include, e = exclude;
        include = e + num[j];
        exclude = Math.max(e, i);
    }
    return Math.max(include, exclude);
}

代码(c++)

维持三个位置处的变量,pre cur i 三个位置处的变量是相邻的,逐步移动即可,最后一个位置是最大值

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size(); 
        if (n < 2) return n ? nums[0] : 0;
        return max(robber(nums, 0, n - 2), robber(nums, 1, n - 1));
    }
private:
    int robber(vector<int>& nums, int l, int r) {
        int pre = 0, cur = 0;
        for (int i = l; i <= r; i++) {
            int temp = max(pre + nums[i], cur);
            pre = cur;
            cur = temp;
        }
        return cur;
    }
};

复杂度

时间负责度为O(N),空间复杂度为O(1), 用两个变量逐步记录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值