- 题目: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.
- 去掉背景题目大意是:给出一串无序整数序列A,要求找出子序列B,要求B不得去A中相邻的元素,是的B的和最大。
如:A={3,1,1,8}最大子序列和为11,B={3,8}
- 一个简单的动态规划问题,递归方程如下:
定义d[i]表示取序列A前i个数的最大子序列和,A[i]表示序列A的第i个元素
基本想法:因为题目要求不能取相邻元素,那么假设取了元素A[i-1]那么就无法取元素A[i],所以当遍历到元素A[i]时,假设d[i-2]加上A[i-1]大还是加上A[i]大。
- 代码如下:
1 public class Solution { 2 public int rob(int[] nums) { 3 if (nums.length == 0) 4 return 0; 5 int[] d = new int[nums.length + 1]; 6 d[0] = 0; 7 d[1] = nums[0]; 8 for (int i = 1; i < nums.length; ++i) { 9 d[i + 1] = (d[i] >= d[i - 1] + nums[i]) ? d[i] 10 : (d[i - 1] + nums[i]); 11 } 12 return d[nums.length]; 13 } 14 }
这是我刚开始提交的代码,后来看了题目讨论区,也发现自己用一个数组将所有过程值保留时没必要的,只需要保留前面两个的子问题值即可,优化:
1 public class Solution { 2 public int rob(int[] nums) { 3 int pre_2 = 0; 4 int pre = 0; 5 for (int i = 0; i < nums.length; ++i) { 6 int tmp = pre; 7 pre = Math.max(pre, pre_2+nums[i]); 8 pre_2 = tmp; 9 } 10 return pre; 11 } 12 }
为了去掉数组为空时的判断,特意将子问题向前推了一个。