题目描述
在 I 的基础上,分成两部分,再取 Max 就行
思路 & 代码
由题意可知:一种路线中,不能同时出现第一家和最后一家。 那么好办了,直接分成两部分分别取:不包含第一家的部分、不包含最后一家的部分 时间复杂度 O(n),空间复杂度 O(n)
class Solution { public int rob ( int [ ] nums) { if ( nums. length == 1 ) { return nums[ 0 ] ; } return Math . max ( forRob ( nums, 0 , nums. length - 2 ) , forRob ( nums, 1 , nums. length - 1 ) ) ; } int forRob ( int [ ] nums, int left, int right) { if ( right - left == 0 ) { return nums[ left] ; } if ( right - left == 1 ) { return Math . max ( nums[ left] , nums[ right] ) ; } int [ ] dp = new int [ right - left + 1 ] ; dp[ 0 ] = nums[ left] ; dp[ 1 ] = nums[ left + 1 ] ; dp[ 2 ] = nums[ left] + nums[ left + 2 ] ; for ( int i = 3 ; i < right - left + 1 ; i++ ) { dp[ i] = nums[ left + i] + Math . max ( dp[ i - 2 ] , dp[ i - 3 ] ) ; } return Math . max ( dp[ right - left] , dp[ right - left - 1 ] ) ; }
}
更新版
注意三个边界判断 更改了思路,当前 dp[i] = 此时可取到的最大值,不一定要取 nums[i]
class Solution { public int rob ( int [ ] nums) { if ( nums. length == 1 ) { return nums[ 0 ] ; } return Math . max ( rob1 ( nums, 0 , nums. length - 2 ) , rob1 ( nums, 1 , nums. length - 1 ) ) ; } public int rob1 ( int [ ] nums, int left, int right) { if ( left == right) { return nums[ left] ; } if ( left + 1 == right) { return Math . max ( nums[ left] , nums[ right] ) ; } int [ ] dp = new int [ nums. length - 1 ] ; dp[ 0 ] = nums[ left] ; dp[ 1 ] = Math . max ( nums[ left] , nums[ left + 1 ] ) ; for ( int i = 2 ; i < dp. length; i++ ) { dp[ i] = Math . max ( dp[ i - 2 ] + nums[ left + i] , dp[ i - 1 ] ) ; } return dp[ dp. length - 1 ] ; }
}