你是一個專業的小偷,計劃偷竊沿街的房屋。每間房內都藏有必定的現金,影響你偷竊的惟一制約因素就是相鄰的房屋裝有相互連通的防盜系統,若是兩間相鄰的房屋在同一夜被小偷闖入,系統會自動報警。
給定一個表明每一個房屋存放金額的非負整數數組,計算你在不觸動警報裝置的狀況下,可以偷竊到的最高金額。
示例 1:java
輸入: [1,2,3,1]
輸出: 4
解釋: 偷竊 1 號房屋 (金額 = 1) ,而後偷竊 3 號房屋 (金額 = 3)。
偷竊到的最高金額 = 1 + 3 = 4 。數組
示例 2:code
輸入: [2,7,9,3,1]
輸出: 12
解釋: 偷竊 1 號房屋 (金額 = 2), 偷竊 3 號房屋 (金額 = 9),接着偷竊 5 號房屋 (金額 = 1)。
偷竊到的最高金額 = 2 + 9 + 1 = 12 。leetcode
假設dp[ i ]爲前 i 間房屋所能獲得的最大利益,那麼dp[ i ]爲如下兩種狀況的最大值:1.第 i 間房屋不偷,則當前最大利益爲前 i - 1 間房的最大利益,即dp[ i ] = dp[ i - 1 ];2.第 i 間房屋偷,則當前最大利益爲前 i - 2 間房的最大利益加上第 i 間房的利益,即dp[ i ] = d[ i - 2 ] + nums[ i ];(相鄰兩間房屋不能偷)
狀態轉移方程:dp[ i ] = max{ dp[ i - 1 ],dp[ i - 2 ] + nums[ i ] }get
class Solution { public int rob(int[] nums) { if(nums.length == 0) return 0; if(nums.length == 1) return nums[0]; int[] dp = new int[nums.length]; dp[0] = nums[0]; dp[1] = Math.max(nums[0], nums[1]); for(int i = 2; i < nums.length; i++){ dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]); } return dp[nums.length - 1]; } }
若是兩間相鄰的房屋在同一夜被小偷闖入,系統會自動報警(即相鄰的數字不能同時做爲最終求和的有效數字)。那麼咱們很容易聯想到求出奇數和以及偶數和,比較這兩個誰更大,誰就是最優解。事實上還有一種狀況可能出現最優解,即部分是奇數和,部分是偶數和,例如[3,1,1,5,1,7,1]這樣的房屋排列,不管小偷偷奇數位置的房屋仍是偶數位置的房屋都不能偷得最多的錢。因此咱們在求和時還要將奇數和或偶數和更新爲當前最大和,以致於當前和老是處於最優的狀態。最後返回兩個和中的最大值。io
class Solution { public int rob(int[] nums) { int sumEven = 0; int sumOdd = 0; for(int i = 0; i < nums.length; i++){ if(i % 2 == 0){ sumEven += nums[i]; sumEven = Math.max(sumEven, sumOdd); }else{ sumOdd += nums[i]; sumOdd = Math.max(sumEven, sumOdd); } } return Math.max(sumEven, sumOdd); } }