题目描述
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
解题思路:
- 环状排列房间问题约化为两个单排排列房间子问题
- 在不偷窃第一个房子的情况下[0,n-2],最大金额是 p1
- 在不偷窃最后一个房子的情况下[1,n-1],最大金额是 p2
- 对两个子问题分别解决.
dp[i]数组定义:在规定区间内偷窃到的最大金额.
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i- 1])
static int rob(int[] nums) {
int n = nums.length;
if (nums == null || nums.length == 0) {
return 0;
}
if (n == 1) {
return nums[0];
}
if (n == 2) {
return Math.max(nums[0], nums[1]);
}
return Math.max(solu(nums, 0, n - 2), solu(nums, 1, n - 1));
}
static int solu(int[] nums, int s, int e) {
int n = nums.length;
int[] dp = new int[n];
dp[s] = nums[s];
dp[s + 1] = Math.max(nums[s + 1], nums[s]);
for (int i = s + 2; i <= e; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i- 1]);
}
return dp[e];
}
踩坑点:
- 在指定区间内求解dp数组时,注意数组的起始与结束
dp[s] = nums[s];
dp[s + 1] = Math.max(nums[s + 1], nums[s]);
Q.E.D.