題目描述
你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個地方所有的房屋都圍成一圈,這意味着第一個房屋和最後一個房屋是緊挨着的。同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被小偷闖入,系統會自動報警。
給定一個代表每個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的情況下,能夠偷竊到的最高金額。
示例1
輸入: [2,3,2]
輸出: 3
解釋: 你不能先偷竊 1 號房屋(金額 = 2),然後偷竊 3 號房屋(金額 = 2), 因爲他們是相鄰的。
示例2
輸入: [1,2,3,1]
輸出: 4
解釋: 你可以先偷竊 1 號房屋(金額 = 1),然後偷竊 3 號房屋(金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。
解題思路:
使用動態規劃求解
因爲是循環數組,那麼可以分爲兩種情況
1、選擇偷竊第一個房屋,那麼就不能選擇最後一個房屋
2、選擇偷竊最後一個房屋,那麼就不能選擇第一個房屋
3、取兩者最大值
每一種情況都是與 LeetCode198—打家劫舍 的算法思想和編碼過程基本一致
下面爲AC代碼:
class Solution {
public:
int rob(vector<int>& nums) {
//核心原則就是,第一個和最後一個不能同時搶,然後選出最大的方案
if(nums.size() <= 0){
return 0;
}
if(nums.size() == 1){
return nums[0];
}
if(nums.size() == 2){
return max(nums[0],nums[1]);
}
//不搶最後一個房屋
vector<int> dp1(nums.size() - 1,0);
dp1[0] = nums[0];
dp1[1] = max(nums[0],nums[1]);
for(int i = 2;i < nums.size() - 1;i++){
dp1[i] = max(dp1[i - 1],dp1[i - 2] + nums[i]);
}
//不搶第一個房屋
vector<int> dp2(nums.size(),0);
dp2[0] = 0;//表示不搶第一個
dp2[1] = nums[1];
for(int i = 2;i < nums.size();i++){
dp2[i] = max(dp2[i - 1],dp2[i - 2] + nums[i]);
}
return max(dp1[nums.size() - 2],dp2[nums.size() - 1]);
}
};
做完這道題可以試試高級版的 LeetCode337—打家劫舍Ⅲ
高級版的給出的結構是樹。