题目
思路
- 思路一:暴力递归,由于不能连续偷窃,因此对于第i个房间有两种选择,偷与不偷,因此我们定义recur(int[] nums, int i)表示0到i中能偷窃的最大金额,其中递归分支是Math.max(recur(nums, i -2) + nums[i], recur(nums, i -1),将问题分解成小问题,当i<0时就是递归终止条件
- 思路二:备忘录
- 思路三:动态规划,递归的逆过程,定义dp[i]表示0到i中能够窃取的最大金额,转移方程:dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1])。初始状态:dp[0] = nums[0],dp[1] = Math.max(nums[0],nums[1])
- 思路四:优化dp数组的动态规划
代码
//1.暴力递归,超时 public int rob(int[] nums) { return recur(nums, nums.length - 1); } public int recur(int[] nums, int i) { if (i < 0) return 0; return Math.max(recur(nums, i - 2) + nums[i], recur(nums, i - 1)); } //2.备忘录,超时 int[] dp; public int rob(int[] nums) { dp = new int[nums.length]; return recur(nums, nums.length - 1); } public int recur(int[] nums, int i) { if (i < 0) return 0; if (dp[i] != 0) return dp[i]; dp[i] = Math.max(recur(nums, i - 2) + nums[i], recur(nums, i - 1)); return dp[i]; } //3.动态规划 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 - 2] + nums[i], dp[i - 1]); } return dp[nums.length - 1]; } //4.优化dp数组的动态规划 public int rob(int[] nums) { if (nums.length == 0) return 0; if (nums.length == 1) return nums[0]; int p1 = nums[0], p2 = Math.max(nums[0],nums[1]), t = 0; for (int i = 2; i < nums.length; i++) { t = Math.max(p1 + nums[i], p2); p1 = p2; p2 = t; } return p2; }
打家劫舍