213. House Robber II

思路:
最近发现动规很多都是从后面开始想,这题就是先考虑,第一个房子不偷和最后一个房子不偷的情况。
第一个房子不偷,就是nums[1:],最大金额是P2,最后一个房子不偷,就是nums[:n-1],最大金额是P1,那么取max(P2,P1)

对于第n个房子,如果偷了第n-1个房子,那么第n个就不偷,那么就会偷第n+1个房子;如果不偷第n-1个房子,那么就偷第n个,不会偷第n+1个。
那么转移方程为 dp[n+1] = max(dp[n-1]+nums[i+1],dp[n])。
第n间可能没有被偷,但仍然把dp[n]取上次最大值,dp[n]=dp[n-1],因为不需要判断哪些房子被偷只要记录总的金额,那么就可以将两种情况合并成一种考虑并不会影响结果。可以用例子:2,7,9,3,1退一下,加1的那步就体现出来了。
又因为最后房子和第一个房子算相邻,我们需要遍历两次nums,第一次是偷第一个房子,第二次是不偷第一个房子,从第二个房子开始。

但我们可以不用dp数组,而使用一个变量临时存,就能获得常数空间复杂度。如下
代码:

class Solution {
public:
    int dp(vector<int>& nums,int start,int end){
        int first=nums[start],second=max(nums[start+1],nums[start]);
        for(int i=start+2;i<=end;++i){
            int temp=second;
            second=max(first+nums[i],second); //转移方程
            first=temp;
        }
        return second;
    }
    int rob(vector<int>& nums) {
        int n=nums.size();
        if(n==1) return nums[0];
        if(n==2) return max(nums[0],nums[1]);
        return max(dp(nums,0,n-2),dp(nums,1,n-1));  //偷第一个房子和不偷第一个房子的两个情况
    }
};

时间复杂度为O(n),空间复杂度为O(1)

posted @ 2021-04-15 11:51  Mrsdwang  阅读(24)  评论(0编辑  收藏  举报