動態規劃——C++做打家劫舍Ⅰ,暴力動態解法+備忘錄解法+降低空間複雜度解法

house robberⅠ

思路:

對每一個當下的房子只有兩個選擇:搶或者不搶,搶的話下一個判斷要在當下+2的位置,不搶的話可以去面對下一間房子
狀態選擇,清晰明瞭:dp[i] = max(dp[i+2]+nums[i], dp[i])

代碼,暴力動態

//關注當下,對房子就兩個選擇,對這個房子偷或者不偷
class Solution {
public:
    int dp(vector<int>&nums, int start)
    {
        if(nums.size() == 0)
            return 0;
        if(start >= nums.size())
            return 0;
        return max(dp(nums,start+1), dp(nums, start+2)+nums[start]);
    }
    int rob(vector<int>& nums) {
        return dp(nums, 0);
    }
};

不幸的是,超時了,ok,加個備忘錄,加備忘錄其實就是在複述一下上述代碼再加個memo

//關注當下,對房子就兩個選擇,對這個房子偷或者不偷
class Solution {
public:
    int dp(vector<int>&nums, int start, vector<int>&memo)
    {
        if(memo[start] != -1) 
            return memo[start];

        if(nums.size() == 0)
            return 0;
        if(start == nums.size())
            return 0;
        if(start == nums.size()-1)
           {
             memo[start] = nums[start];
            return memo[start];
        }
        memo[start] = max(dp(nums,start+1, memo), dp(nums, start+2, memo)+nums[start]);
        return memo[start];
    }
    int rob(vector<int>& nums) {
        vector<int> memo(nums.size()+1, -1);//初始化爲-1
        return dp(nums, 0, memo);
    }
};

降低空間複雜度解法

因爲狀態轉移只與最近的兩個狀態有關,所以可以進一步優化,將空間複雜度降低到O(1),
先寫一下dp數組的:dp[i]= x表示從第i間房開始最多能搶到x, dp[i] = max(dp[i], dp[i+2]+nums[i])

dp數組代碼

class Solution {
public:
    int rob(vector<int>& nums) {//dp[i]表示從第n間房開始搶可以搶到的最大數
        int n = nums.size();
        //int dp[n+2];
        vector<int>dp(n+2, 0);
        dp[n] = 0;//base case從n開始搶, 最後一間房是n-1,所以搶個空, 找到狀態,遍歷狀態,所以去遍歷房間數
        for(int i = n-1; i>=0; i--)
        {
            dp[i] = max(dp[i+1], dp[i+2]+nums[i]);
        }
        return dp[0];//從最後開始搶,那麼只要返回最後的結果就行,就是第一間房
    }
};

降低空間複雜度代碼

因爲當前狀態只與前兩個狀態相關,所以只需要用變量保留前兩個狀態就行,不需要用dp數組將所有的狀態保留下來

class Solution {
public:
    int rob(vector<int>& nums) {
        int n = nums.size();
        int dp_i_1 = 0;//不搶
        int dp_i_2 = 0;//搶
        int dp_i = 0;
        for(int i= n-1; i>=0; i--)
        {
            dp_i = max(dp_i_1, dp_i_2+nums[i]);
            dp_i_2 = dp_i_1;
            dp_i_1 = dp_i;
        }
        return dp_i;//i就是當前的節點,遍歷完就是最後的節點

    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章