You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.數組
Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.優化
時間 O(N) 空間 O(1)code
通常來講,給定一個規則,讓咱們求任意狀態下的解,都是用動態規劃。這裏的規則是劫匪不能同時搶劫相鄰的屋子,即咱們在累加時,只有兩種選擇:it
若是選擇了搶劫上一個屋子,那麼就不能搶劫當前的屋子,因此最大收益就是搶劫上一個屋子的收益io
若是選擇搶劫當前屋子,就不能搶劫上一個屋子,因此最大收益是到上一個屋子的上一個屋子爲止的最大收益,加上當前屋子裏有的錢class
因此,咱們只要判斷一下兩個裏面哪一個大就好了,同時也是咱們的遞推式。另外咱們能夠作一點優化,原本咱們是要用一個dp數組來保存以前的結果的。但實際上咱們只須要上一次和上上次的結果,因此能夠用兩個變量就好了。變量
public class Solution { public int rob(int[] nums) { if(nums.length <= 1){ return nums.length == 0 ? 0 : nums[0]; } // a是上次的最大收益 int a = nums[0]; // b是當前的最大受益 int b = Math.max(nums[0], nums[1]); for(int i = 2; i < nums.length; i++){ int tmp = b; // 當前的最大收益是兩種選擇裏較大的那個 b = Math.max(a + nums[i], b); a = tmp; } return b; } }
時間 O(N) 空間 O(1)im
和I同樣,可是這裏多了一條規則,抽象出來就是:搶劫第一個屋子就不能搶劫最後一個屋子,搶劫最後一個屋子就不能搶劫第一個屋子。因此咱們分別算出這兩個條件下的最大收益,而後取更大的就好了。能夠複用I的代碼。call
public class Solution { public int rob(int[] nums) { // 求兩種條件下更大的那個,用一個offset表示是哪一種條件 return Math.max(rob(nums, 0), rob(nums, 1)); } public int rob(int[] nums, int offset) { // 若是長度太小,則直接返回結果 if(nums.length <= 1 + offset){ return nums.length <= offset ? 0 : nums[0 + offset]; } int a = nums[0 + offset]; // 若是offset是1,則從下標爲1的元素開始計算,因此要比較nums[1]和nums[2] int b = Math.max(nums[0 + offset], nums[1 + offset]); // 對於不搶劫最後一個房子的狀況,i要小於nums.length - 1 for(int i = 2 + offset; i < nums.length - 1 + offset; i++){ int tmp = b; b = Math.max(a + nums[i], b); a = tmp; } return b; } }