本文最后更新于:2021年1月30日 上午
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,能够偷窃到的最高金额。
示例 1:
| 输入:nums = [2,3,2] 输出:3 解释:你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。
|
示例 2:
| 输入:nums = [1,2,3,1] 输出:4 解释:你可以先偷窃 1 号房屋(金额 = 1),然后偷窃 3 号房屋(金额 = 3)。 偷窃到的最高金额 = 1 + 3 = 4 。
|
示例 3:
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 1000
Solution
参考:《算法小抄》2.18
- 环形数组
- 首先,首尾房间不能同时被抢,那么只可能有三种不同情况:要么都不被抢;要么第一间房子被抢最后一间不抢;要么最后一间房子被抢第一间不抢。
- 只要比较情况二和情况三就行,因为这两种情况对于房子的选择余地比情况一大呀,最优决策结果肯定不会小。
| class Solution: def rob(self, nums: List[int]) -> int: if len(nums)==1: return nums[0] def subRob(nums): cur, pre1, pre2 = 0,0,0 for num in nums: cur = max(pre1, pre2+num) pre2 = pre1 pre1 = cur return cur return max(subRob(nums[:-1]), subRob(nums[1:]))
|
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { private: int go(const vector<int>& nums, int index, int l, int r){ int pre1 = 0, pre2=0, cur = 0; for(int i=l; i<r; ++i){ cur = max(nums[i]+pre2, pre1); pre2 = pre1; pre1 = cur; } return cur; }
public: int rob(vector<int>& nums) { int n = nums.size(); if(n==0) return 0; if(n==1) return nums[0];
int res1 = go(nums, 0, 0, n-1); int res2 = go(nums, 1, 1, n); return max(res1, res2); } };
|