leetcode题解(一)

题目:213.House Robber II

题目链接

https://leetcode.com/problems/house-robber-ii/description/

题目描述
你是一个专业的强盗,计划抢劫沿街的房屋。每间房都藏有一定的现金,阻止你抢劫他们的唯一的制约因素就是相邻的房屋有保安系统连接,如果两间相邻的房屋在同一晚上被闯入,它会自动联系警方。

给定一个代表每个房屋的金额的非负整数列表,确定你可以在没有提醒警方的情况下抢劫的最高金额。

在上次盗窃完一条街道之后,窃贼又转到了一个新的地方,这样他就不会引起太多注意。这一次,这个地方的所有房屋都围成一圈。这意味着第一个房子是最后一个是紧挨着的。同时,这些房屋的安全系统与上次那条街道的安全系统保持一致。

给出一份代表每个房屋存放钱数的非负整数列表,确定你可以在不触动警报的情况下盗取的最高金额。
解题思路
这是一道动态规划问题,将房子编号为1~n,设M[i]为盗贼到第i间房子时,盗取的最高金额,设V[i]表示第i间房子的金额。  

盗贼一定会偷尽可能多的房屋,即当他偷到第n-4间房子时,他不会就此罢手,而一定会去偷第n-2、n-1间房子。  

他也不会直接从第n-4间房子直接到第n间房子偷窃,因为这就少偷了第n-2间房子。  

基于上述判断,我们可以断言,当盗贼偷窃第i间房子时,他一定是从第i-2或第i-3间房子过来的,即:  

M[i] = max(M[i-2], M[i-3]) + V[i]  

接下来考虑边界条件:  

如果房子不是围成一圈(即第1间房子和第n间房子不相邻),那么盗贼盗取的最高金额必为max(M[n-1], M[n]),且为了最大收益,盗贼第一次盗取的房子一定是第1间或第2间。  

如果房子围成一圈,我们仍可以用遍历的方式求解,当盗贼盗取了最高金额的前提下,还需要考虑以下情况:  

1、若盗贼最后盗取的房子为第n间,那么他第一次盗取的房子一定不是第1间  

2、若盗贼最后盗取的房子为第n间,那么他第一次盗取的房子可能是第3间  

3、若盗贼第一次盗取的房子是第1间,那么他最后盗取的房子可能是第n-2间  

用M[i][j]表示盗贼第一次盗取的房子为第i间时(1<=i<=3),盗取第j间房子能得到的最大收益,则盗贼盗取的最大金额必为:  

M[2][n], M[3][n], M[1][n-1], M[2][n-1], M[1][n-2]中的最大值  
代码
int x = [](){
    std::ios::sync_with_stdio(false);
    cin.tie(nullptr);
    return 0;
}();

class Solution {
public:
    int pre(vector<int> arr[],int j,int i){
        if(i-3<0)return arr[j][i-2];
        return max(arr[j][i-2],arr[j][i-3]);
    }
    int rob(vector<int>& nums) {
        if(!nums.size())return 0;
        vector<int> arr[3]={vector<int>(nums.size(),0),vector<int>(nums.size(),0),vector<int>(nums.size(),0)};
        arr[0][0]=nums[0];
        if(nums.size()>1)arr[1][1]=nums[1];
        if(nums.size()>2)arr[2][2]=nums[2];
        for(int i=2;i<nums.size();++i){
            for(int j=0;j<3;++j){
                arr[j][i]=pre(arr,j,i)+nums[i];
            }
        }
        if(nums.size()<2)return arr[0][0];
        int maxn=max(arr[1][nums.size()-1],max(arr[0][nums.size()-2],arr[1][nums.size()-2]));
        if(nums.size()<3)return maxn;
        return max(maxn,max(arr[2][nums.size()-1],max(arr[1][nums.size()-3],arr[0][nums.size()-3]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值