leetcode动态规学习(二)

打家劫舍问题

leetcode动态规学习(二)_第1张图片

class Solution {
public:
    int rob(vector<int>& nums) {
        
        vector<int>dp(nums.size(),0);
        int M=nums.size();
        if(M<=0) return 0;
        if(M==1) return nums[0];
        if(M==2) return max(nums[0],nums[1]);
        dp[0]=nums[0];
        dp[1]=max(nums[0],nums[1]);
        int res=INT_MIN;
        for(int i=2;i<nums.size();i++)
        {
            dp[i]=max((dp[i-2]+nums[i]),dp[i-1]);
            cout<<dp[i];
            // res=max(res,dp[i]);
        }

        return dp[M-1];
    }
};

通过奇数偶数来判断 来源

还有一种解法,核心思想还是用 DP,分别维护两个变量 robEven 和 robOdd,顾名思义,robEven 就是要抢偶数位置的房子,robOdd 就是要抢奇数位置的房子。所以在遍历房子数组时,如果是偶数位置,那么 robEven 就要加上当前数字,然后和 robOdd 比较,取较大的来更新 robEven。这里就看出来了,robEven 组成的值并不是只由偶数位置的数字,只是当前要抢偶数位置而已。同理,当奇数位置时,robOdd 加上当前数字和 robEven 比较,取较大值来更新 robOdd,这种按奇偶分别来更新的方法,可以保证组成最大和的数字不相邻,最后别忘了在 robEven 和 robOdd 种取较大值返回,代码如下

class Solution {
public:
    int rob(vector<int>& nums) {
        
        int robEven=0;
        int robOdd=0;
        int n=nums.size();

        for(int i=0;i<n;i++)
        {
            if(i%2==0){
                robEven=max(robEven+nums[i],robOdd);
            }else{
                robOdd=max(robOdd+nums[i],robEven);
            }

           
        }
         return max(robEven,robOdd);

    }
};

压缩空间

我们注意到
dp[i] 只和dp[i-1] dp[i-2] 这两个状态有关所以我们可以 用两个变量来保存有关的值 类似滚动数组

int rob(vector<int>& nums) {
    int prev = 0;
    int curr = 0;

    // 每次循环,计算“偷到当前房子为止的最大金额”
    for (int i : nums) {
        // 循环开始时,curr 表示 dp[k-1],prev 表示 dp[k-2]
        // dp[k] = max{ dp[k-1], dp[k-2] + i }
        int temp = max(curr, prev + i);
        prev = curr;
        curr = temp;
        // 循环结束时,curr 表示 dp[k],prev 表示 dp[k-1]
    }

    return curr;
}

你可能感兴趣的:(leetcode)