LeetCode 198. House Robber

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.

Credits:
Special thanks to @ifanchu for adding this problem and creating all test cases. Also thanks to @ts for adding additional test cases.

【题目分析】

这是一个很经典的动态规划的题目,意思是一个盗贼要偷盗一条街道上的店铺。唯一的限制就是不能同时偷盗连续的两家店铺,否则的话报警器就会被触发,求在不触发警报的情况下该盗贼可偷盗的最多金钱数。

【思路】

1. 用递归来解决

盗贼遍历店铺,从当前店铺开始获取的最大收益 = max(偷盗当前店铺获取的最大收益, 不偷盗当前店铺获取的最大收益)

代码如下:

 1 public class Solution {
 2     public int rob(int[] nums) {
 3         return robber(nums, 0);
 4     }
 5
 6     public int robber(int[] nums, int start) {
 7         if(start > nums.length-1) return 0;
 8         if(start == nums.length-1) return nums[start];
 9         int result1 = 0, result2 = 0;
10         result1 = nums[start] + robber(nums, start+2);
11         result2 = robber(nums, start+1);
12
13         return result1 > result2 ? result1 : result2;
14     }
15 }

上面的代码时间复杂度较高。原因在于递归的时候一些中间的计算结果没有保存下来,导致多次计算已经计算后的结果。对上面的代码进行改进如下:

 1 public class Solution {
 2     public int rob(int[] nums) {
 3         int[] mark = new int[nums.length];
 4         for(int i = 0; i < nums.length; i++) {
 5             mark[i] = -1;
 6         }
 7         return robber(nums, mark, 0);
 8     }
 9
10     public int robber(int[] nums, int[] mark, int start) {
11         if(start > nums.length-1) return 0;
12         if(start == nums.length-1) return nums[start];
13         int result1 = 0, result2 = 0;
14         if(start+2 < nums.length && mark[start+2] > -1) {
15             result1 = nums[start] + mark[start+2];
16         } else {
17             result1 = nums[start] + robber(nums, mark, start+2);
18         }
19
20         if(start+1 < nums.length && mark[start+1] > -1) {
21             result2 = mark[start+1];
22         } else {
23             result2 = robber(nums, mark, start+1);
24         }
25
26         mark[start] = result1 > result2 ? result1 : result2;
27         return mark[start];
28     }
29 }

上面的代码用mark数组保存了已经计算过的最优值,递归过程中如果发现该值已经被计算过,则直接取出已经计算过的结果即可。

递归表达式为:rob[start] = max(rob[start+1], nums[start] + rob[start+2])

上面的代码太过冗余,优化后的代码如下:

 1 public class Solution {
 2     public int rob(int[] nums) {
 3         int len = nums.length;
 4         if(len == 0) return 0;
 5         if(len == 1) return nums[0];
 6
 7         int[] mark = new int[len];
 8         mark[len-1] = nums[len-1];
 9         mark[len-2] = Math.max(nums[len-1], nums[len-2]);
10
11         for(int i = len-3; i >= 0; i--) {
12             mark[i] = Math.max(mark[i+1], nums[i] + mark[i+2]);
13         }
14         return mark[0];
15     }
16 }

上面代码的空间复杂度为O(n),我们发现其实不必把已经计算过的所有信息保存下来,只要保存后两个记录即可,优化后的空间复杂度为O(1),代码如下:

 1 public class Solution {
 2     public int rob(int[] nums) {
 3         int len = nums.length;
 4         if(len == 0) return 0;
 5         if(len == 1) return nums[0];
 6
 7         int post2 = nums[len-1];
 8         int post1 = Math.max(nums[len-2], nums[len-1]);
 9
10         for(int i = len-3; i >= 0; i--) {
11             int temp = post1;
12             post1 = Math.max(post1, nums[i] + post2);
13             post2 = temp;
14         }
15         return post1;
16     }
17 }
时间: 2024-10-15 17:21:06

LeetCode 198. House Robber的相关文章

leetCode 198. House Robber | 动态规划

198. House Robber 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

[LeetCode] 198. House Robber Java

题目: 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 a

leetcode 198. House Robber 求抢劫的最大金额 ---------- java

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 autom

Java for LeetCode 198 House Robber

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 autom

leetcode——198 House Robber(寻找数组不相邻组合最大值—动态规划问题)

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed(藏着), </span> the onl

动态规划系列 Leetcode 198. House Robber

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 autom

leetcode 198. House Robber (Easy)

https://leetcode.com/problems/house-robber/ 题意: 一维数组,相加不相邻的数组,返回最大的结果. 思路: 一开始思路就是DP,用一维数组保存dp[i]保存如果偷第i间,此时可偷到多少.DP的方向不太好,所以效率很低. Runtime: 4 ms, faster than 17.53% class Solution { public: int rob(vector<int> &nums) { int res = 0; int len = num

leetcode 198 House Robber I

function rob(nums) { if(!nums || nums.length === 0) { return 0; } else if(nums.length < 2){ return nums[0]; } let memo = new Array(nums.length); memo[0] = nums[0]; memo[1] = Math.max(nums[0], nums[1]); for(let i = 2; i < nums.length; i++) { memo[i]

LeetCode 198, 213 House Robber

198 House Robber DP 0~n-1     ans=dp[n-1] dp[i] = max(dp[i-2]+nums[i], dp[i-1])  i>=2 213 House Robber II Since we cannot rob nums[0] and nums[n-1] at the same time, we can divide this problem into two cases: not rob nums[0] not rob nums[n-1] and the