import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param nums int整型一维数组 * @return int整型 */ public int rob (int[] nums) { // write code here // 动态规划 - dp[i]表示偷到第i家(偷or不偷)的最大收益 // 注意!由于是循环数组,因此需要通过【分类讨论】的方式将其拆成【若干不循环数组】的情况,仿照【打家劫舍(一)】的套路解决即可 int n = nums.length; if (n == 1) { return nums[0]; } // case1 - 偷0号,不偷n-1号 int[] dp1 = new int[n]; // 偷0号 dp1[0] = nums[0]; for (int i = 1; i < n - 1; i++) { // 选择偷i号的收益 int yes = nums[i]; if (i - 2 >= 0) { // i位置本身的金额,加上i-2处的最大收益 yes += dp1[i - 2]; } // 选择不偷i号的收益 int no = 0; if (i - 1 >= 0) { // i-1位置本身的最大收益 no += dp1[i - 1]; } // i位置的最大收益为偷or不偷两种情况收益的最大值 dp1[i] = Math.max(yes, no); } // 不偷n-1号 dp1[n - 1] = dp1[n - 2]; // case2 - 不偷0号,偷n-1号 int[] dp2 = new int[n]; // 不偷0号 dp2[0] = 0; for (int i = 1; i < n - 1; i++) { // 选择偷i号的收益 int yes = nums[i]; if (i - 2 >= 0) { // i位置本身的金额,加上i-2处的最大收益 yes += dp2[i - 2]; } // 选择不偷i号的收益 int no = 0; if (i - 1 >= 0) { // i-1位置本身的最大收益 no += dp2[i - 1]; } // i位置的最大收益为偷or不偷两种情况收益的最大值 dp2[i] = Math.max(yes, no); } // 偷n-1号 dp2[n - 1] = dp2[n - 3] + nums[n - 1]; // 返回两种分类讨论的最大值 return Math.max(dp1[n - 1], dp2[n - 1]); } }