题目描述
在 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 ] ;
}
}