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; } }