题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
题目描述
你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
示例 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:
输入:nums = [1,2,3] 输出:3
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 1000
跟我之前写的打家劫舍1的解法只是当前数组能不能成环,不成环就是头尾互不影响,成环就是头尾互相影响,选这个就不能选那个
具体看代码
package dataStructure.bigFactory.chapter33;
/**
* 你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都 围成一圈 ,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警 。
*
* 给定一个代表每个房屋存放金额的非负整数数组,计算你 在不触动警报装置的情况下 ,今晚能够偷窃到的最高金额。
*
*
*
* 示例 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:
*
* 输入:nums = [1,2,3]
* 输出:3
*
*
* 提示:
*
* 1 <= nums.length <= 100
* 0 <= nums[i] <= 1000
*/
public class _213HouseRobberII {
/**
* 题意太长,我总结一下对比打家劫舍1的区别就是当前的数组可以认为是一个环,0和N-1也相邻
* 所以放0的话就不能放N-1,方N-1的话就不能放0
* @param nums
* @return
*/
public int rob(int[] nums) {
/**
* 题目规定了数据范围,这里不会走,所以你爱写不写,我是个人习惯
*/
if(nums == null || nums.length == 0) {
return 0;
}
int N = nums.length;
if(N == 1) {
return nums[0];
}
if(N == 2) {
return Math.max(nums[0], nums[1]);
}
/**
* 大于2的情况的处理,使用动态规划,先定义两个dp数组:dpFromZero和dpFromOne
* dpFromZero[i]表示是从0~i的最大收益
* dpFromOne[i]表示1~i+1的最大收益,这个比较特殊,i=0代表1~1,i=1代表1~2
* 这里有两个原因要这么写:1 为了不浪费0位置 2 为了和dpFromZero对齐,最后都取[N-2]
* 如果你不能理解就成成长度=N,然后遍历从1开始也无所谓
*/
int[] dpFromZero = new int[N - 1];
int[] dpFromOne = new int[N - 1];
/**
* 简单的初始化过程:初始化前两个值
* 第一个没得选择,第二个从前两个价值里选最大
*/
dpFromZero[0] = nums[0];
dpFromZero[1] = Math.max(nums[0], nums[1]);
dpFromOne[0] = nums[1];
dpFromOne[1] = Math.max(nums[1], nums[2]);
/**
* 初始化dp[0]和[1]之后,从2开始剩余的赋值(最大N-2)
* 这里从2开始是因为0和1位置可以特殊处理,然后后面每个位置i依赖于i-1和i-2的值
*/
for(int i = 2; i < N - 1; i++) {
/**
* 当前位置的选择:1 当前位置的不要,等同于dpFromZero[i-1] 2 当前位置要,加上0~i-2能获得的最大价值(dpFromZero[i-2])
* 二者取最大
*/
dpFromZero[i] = Math.max(dpFromZero[i - 1], nums[i] + dpFromZero[i -2]);
/**
* dpFromOne同理,只是当前位置的值这里要注意不是nums[i],而是nums[i+1]
*/
dpFromOne[i] = Math.max(dpFromOne[i - 1], nums[i + 1] + dpFromOne[i - 2]);
}
return Math.max(dpFromZero[N-2], dpFromOne[N-2]);
}
}
提交结果:
看不懂欢迎私信交流