目录
- 一、题目
- 二、思路
- 1.递归
- 2.递推
- 三、代码
一、题目
二、思路
1.递归
题目中指出不可以选相邻的房间,说明如果选了第 1 间,那么第 2 间一定不可以选,第 3 间房间可以选,也可以不选……假设是按照从第 1 间房间开始依次往后选,每一间房间的选择都会影响到后面的房间可不可以被选择。
对于每间房子(i)都是只有两种选择的,要么选要么不选,假设解决当前问题的函数为 dfs():
- 不选第 i 间:那么可以考虑被选不选第 i - 1间房,相当于将问题规模缩小到了求解 i - 1间房间可以获得的最高金额,即从 dfs(i) 缩小到了 dfs(i - 1)
- 选第 i 间:与之相邻的第 i - 1间房肯定没有被选,再继续往回倒推,第 i - 2 间房间可以考虑被选择。选第 i 间房的获得金额 nums[i] 是确定的,那么总共的最大金额就取决于前 i - 2 间房子得到的最大金额,即将问题变为 dfs(i - 2) + nums[i]
综上,对于第 i 间房的选择一共有两种情况,只要选择总金额最高的那个就好,于是 ans = max(dfs(i - 1), dfs(i - 2) + nums[i]),写出相应的代码:
class Solution {int[] nums;public int rob(int[] nums) {this.nums = nums;int ans = dfs(nums.length - 1);return ans;}public int dfs(int i) {if (i < 0) {return 0;}int ans = Math.max(dfs(i - 1), dfs(i - 2) + nums[i]);return ans;}
}
但这样提交会发现超时。
2.递推
在递归的基础上,创建一个数组 dp[] 来存储之前计算过的结果,避免重复计算。
dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i])
三、代码
class Solution {public int rob(int[] nums) {int n = nums.length;if (n < 2) {Arrays.sort(nums);return nums[n - 1];}int[] dp = new int[n];// dp[i] 表示从前 i 个房间中可以获得的最高金额dp[0] = nums[0];dp[1] = Math.max(nums[0], nums[1]);for (int i = 2; i < n; i++) {dp[i] = Math.max(dp[i - 1], dp[i - 2] + nums[i]);}return dp[n - 1];}
}