213. 打家劫舍 II -M
阿新 • • 發佈:2019-02-03
213. 打家劫舍 II
你是一個專業的小偷,計劃偷竊沿街的房屋,每間房內都藏有一定的現金。這個 地方所有的房屋都圍成一圈,這意味著第一個房屋和最後一個房屋是緊挨著的。 同時,相鄰的房屋裝有相互連通的防盜系統,如果兩間相鄰的房屋在同一晚上被 小偷闖入,系統會自動報警。 給定一個代表每個房屋存放金額的非負整數陣列,計算你在不觸動警報裝置的情 況下,能夠偷竊到的最高金額。 示例 1: 輸入: [2,3,2] 輸出: 3 解釋: 你不能先偷竊 1 號房屋(金額 = 2),然後偷竊 3 號房屋(金額 = 2), 因為 他們是相鄰的。 示例 2: 輸入: [1,2,3,1] 輸出: 4 解釋: 你可以先偷竊 1 號房屋(金額 = 1),然後偷竊 3 號房屋(金額 = 3)。 偷竊到的最高金額 = 1 + 3 = 4 。
-
分析
相比 198. 打家劫舍 這道題增加了子集中的最優,198那道題,因為 都是正整數,所以{0,i}的集合加和求解就好,213增加了環,所以i=s-1 時,要看集合{1,i-2}的最大值,即無法用原來的動態一維陣列dp,這 一要用二維dp,要用到 dp[0][i]=dp[0][i-2],i=s-1時,dp[0][i]=dp[1][i-2]
如果題目中加了負數,那難度就又提高了。
-
code
package main
import "fmt"
func rob(nums []int) int {
s:=len(nums)
if s==0{
return 0
}
dp:= make([][]int,len(nums))
for i:=0;i<s;i++{
dp[i]=make([]int,s)
dp[i][i]=nums[i]
if i+1<s{
dp[i][i+1]=nums[i+1]
if dp[i][i+1]<dp[i][i]{
dp[i][i+1]=dp[i][i]
}
}
}
for size:=3;size<=s;size++{
for i:=0;i<s-size+1;i++{
if i+size==s{
dp[i][i+size-1]=nums[i+size- 1]+dp[i+1][i+size-3]
}else{
dp[i][i+size-1]=nums[i+size-1]+dp[i][i+size-3]
}
if dp[i][i+size-1]<dp[i][i+size-2]{
dp[i][i+size-1]=dp[i][i+size-2]
}
}
}
return dp[0][s-1]
}
func main(){
fmt.Println(rob([]int{1,2,3,1}))
fmt.Println(rob([]int{2,3,2}))
fmt.Println(rob([]int{3,2}))
}