selected_coding_interview/docs/213. 打家劫舍 II.md
此题是 198. 打家劫舍 的拓展版: 唯一的区别是此题中的房间是 环状排列 的(即首尾相接),而 $198.$ 题中的房间是 单排排列 的;而这也是此题的难点。
环状排列 意味着第一个房子和最后一个房子中 只能选择一个偷窃,因此可以把此 环状排列房间 问题约化为两个 单排排列房间 子问题:
下面的任务则是解决 单排排列房间(即 198. 打家劫舍) 问题。推荐可以先把 $198.$ 做完再做这道题。
典型的动态规划,以下按照标准流程解题。
cur和 pre 交替记录,将空间复杂度降到 $O(1)$ 。nums 需要线性时间;cur和 pre 使用常数大小的额外空间。<,,,,,,,>
class Solution:
def rob(self, nums: [int]) -> int:
def my_rob(nums):
cur, pre = 0, 0
for num in nums:
cur, pre = max(pre + num, cur), cur
return cur
return max(my_rob(nums[:-1]),my_rob(nums[1:])) if len(nums) != 1 else nums[0]
class Solution {
public int rob(int[] nums) {
if(nums.length == 0) return 0;
if(nums.length == 1) return nums[0];
return Math.max(myRob(Arrays.copyOfRange(nums, 0, nums.length - 1)),
myRob(Arrays.copyOfRange(nums, 1, nums.length)));
}
private int myRob(int[] nums) {
int pre = 0, cur = 0, tmp;
for(int num : nums) {
tmp = cur;
cur = Math.max(pre + num, cur);
pre = tmp;
}
return cur;
}
}