leetcode之路(198.打家劫舍 and 213.打家劫舍ii)

leetcode之路(198.打家劫舍 and 213.打家劫舍ii)

198.打家劫舍 題目:

你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有一定的現金,影響你偷竊的唯一制約因素就是相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。

給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。

示例 1:

輸入: [1,2,3,1] 輸出: 4 解釋: 偷竊 1 號房屋 (金額 = 1) ,然後偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。 示例 2:

輸入: [2,7,9,3,1] 輸出: 12 解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5
號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。

“實現一個功能如果需要10分鐘,思考的時間是7分鐘”
思考過程
題意很簡單,意思就是說給定一個非負整數數組,在所取的數不能相鄰的前提下去數組中的數,求這些數的和最大爲多少。向這種求“最大”、“最小”的題目在很多情況下要用到動態規劃的方法。
看到不連續我們首先想到的應該是下圖中的前兩種情況,至於第三種情況有沒有可能是題目的答案呢?當然有可能,比如:數組 [100,1,1,100,1,100,1,100,1,1,100,1,1,100];那麼第四種情況可能是題目的解嗎?
哈哈哈,當然不可能,間隔三個或更多個數字,其中就跳過了可以取的數字(比如圖中的第三個數字),只會使我們取得數字的值變小(爲0時不變,反正不會變大)。
不連續的數組
我們可以從左到右遍歷一遍數組,同時定義一個數組dp來記錄到nums[i]時,我們可以取到的最大的和一定要理解這句話,dp[i]所存放的值是從nums[0]到nums[i]可以取到最大的值);這樣我們的問題就轉換成了到第i個數字取不取的問題,取的話就是dp[i]=dp[i-2]+nums[i](取nums[i]則不能取nums[i-1],dp[i-2]就是當前含nums[i-1]的最大和),不取就是dp[i]=dp[i-1]dp[i-1]就是當前不含nums[i]的最大和)。特殊情況:當i=0時,我們可以取到的最大的值應該是nums[0],所以dp[0]=nums[0],當i=1時,我們可以取到最大的值是數組中前兩個數的最大值,所以dp[1]=max(dp[0],nums[1]);
打家劫舍
附上代碼

#include<vector>
using namespace std;
int dp[100];
class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size()==0)
        return 0;
        for(int index=0;index<nums.size();index++){
            if(index==0) dp[index]=nums[0];
            else if(index==1) dp[index]=max(nums[0],nums[1]);
           else dp[index]=max(nums[index]+dp[index-2],dp[index-1]);
        }
        return dp[nums.size()-1];
    }
};

√ Accepted
√ 69/69 cases passed (0 ms)
√ Your runtime beats 100 % of cpp submissions
√ Your memory usage beats 75.24 % of cpp submissions (8.6 MB)

213打家劫舍ii 題目

你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味着第一個房屋和最後一個房屋是緊挨着的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
示例 1:
輸入: [2,3,2]
輸出: 3
解釋: 你不能先偷竊 1 號房屋(金額 = 2),然後偷竊 3 號房屋(金額 = 2), 因爲他們是相鄰的。
示例 2:
輸入: [1,2,3,1]
輸出: 4
解釋: 你可以先偷竊 1 號房屋(金額 = 1),然後偷竊 3 號房屋(金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。

題意 這題相對上一題的變化時,房屋成環,也就是“取頭不取尾,取尾不取頭”,盡然這樣,那我們就想辦法把這個環給“斷開”,我們可以仍然使用上題中的代碼,**我們從nums[0]到nums[nums.size()-2]計算一次(“有頭的情況”),再從nums1[1]到nums[nums.size()-1]計算一次(“有尾的情況”)。**這麼一來數組的頭和尾一定不會同時取到,我們取兩種情況的最最大值就是答案了。
附上代碼

class Solution {
public:
int dp[100];
//拿頭不拿尾,房屋成環,
//人工斷環,nums去掉第一個數字,算一次,再去掉最後一個數字算一次,取大的即所求
   int rob(vector<int>& nums) {
        if(nums.size()==0)
        return 0;
        if(nums.size()==1)
        return nums[0];
        int ans1,ans2;
        for(int index=0;index<nums.size()-1;index++){
            if(index==0) dp[index]=nums[0];
            else if(index==1) dp[index]=max(nums[0],nums[1]);
           else dp[index]=max(nums[index]+dp[index-2],dp[index-1]);
        }
        ans1=dp[nums.size()-2];
         for(int index=1;index<nums.size();index++){
            if(index==1) dp[index]=nums[1];
            else if(index==2) dp[index]=max(nums[1],nums[2]);
           else dp[index]=max(nums[index]+dp[index-2],dp[index-1]);
        }
        ans2=dp[nums.size()-1];
        return ans1>=ans2?ans1:ans2;
    }
};

提交結果

√ Accepted
√ 74/74 cases passed (0 ms)
√ Your runtime beats 100 % of cpp submissions
√ Your memory usage beats 88.58 % of cpp submissions (8.5 MB)

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