213. 打家劫舍 II

动态规划的题,我先用最初级的方式写出来

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size()==0)
        {
            return 0;
        }
        int n=nums.size();
        if(n==1)
        {
            return nums[0];
        }
        //0为偷,1为不偷
        //dp[i][n]为最大金钱
        //dp[i][0]=dp[i-1][1]+nums[i],dp[i][1]=max(dp[i-1][0],dp[i-1][1]);
        vector<vector<int>>dp(nums.size(),vector<int>(2,0));
        vector<vector<int>>dp2(nums.size(),vector<int>(2,0));
        //不选首节点
        for(int i=1;i<nums.size();i++)
        {
            dp[i][0]=(i-1>=0?dp[i-1][1]:0)+nums[i];
            dp[i][1]=(i-1>=0?max(dp[i-1][0],dp[i-1][1]):0);
        }

        //不选尾节点
        for(int i=0;i<nums.size()-1;i++)
        {
            dp2[i][0]=(i-1>=0?dp2[i-1][1]:0)+nums[i];
            dp2[i][1]=(i-1>=0?max(dp2[i-1][0],dp2[i-1][1]):0);
        }

        return max(max(dp[n-1][0],dp[n-1][1]),max(dp2[n-2][0],dp2[n-2][1]));
    }
};

首尾节点不能同时选也是个比较难处理的点,我在看了别人的答案后写出了以上答案。

如下图,只要考虑情况二和三就好,因为包含了情况一。

 方式二:

class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size()==0)
        {
            return 0;
        }
        int n=nums.size();
        if(n==1)
        {
            return nums[0];
        }
        //0为偷,1为不偷
        //dp[i][n]为最大金钱
        //dp[i][0]=dp[i-1][1]+nums[i],dp[i][1]=max(dp[i-1][0],dp[i-1][1]);
        //优化空间版,只需要记录上一次的偷和不偷就可以了
        int i_0=0,i_1=0;
        //不选首节点
        for(int i=1;i<nums.size();i++)
        {
            //
            int tmp_i_1=(i-1>=0?max(i_0,i_1):0);
            i_0=(i-1>=0?i_1:0)+nums[i];
            i_1=tmp_i_1;
        }

        //不选尾节点
        int j_0=0,j_1=0;
        for(int i=0;i<nums.size()-1;i++)
        {
            int tmp_j_0=(i-1>=0?j_1:0)+nums[i];
            j_1=(i-1>=0?max(j_0,j_1):0);
            j_0=tmp_j_0;
        }

        return max(max(i_0,i_1),max(j_0,j_1));
    }
};
原文地址:https://www.cnblogs.com/wangshaowei/p/13472821.html