动态规划,当前状态由前两个状态获得,滚动数组。
从题可以看出要达到最高金额时,要从相邻的房屋拿。因此是当前房屋的金额隔一个做累加,当然还需要跟前一个相邻的房屋做比较,便于取到哪边金额更高,因此需要一个dp数组做状态维护。
处理好边界问题,然后列出状态转移方程 dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1])。
时间复杂度: O(n),空间复杂度: O(n)。
java
class Solution {
public int rob(int[] nums) {
if (nums == null || nums.length == 0) {
return 0;
}
int length = nums.length;
if (length == 1) {
return nums[0];
}
int[] dp = new int[length];
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (int i = 2; i < length; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[length - 1];
}
}
注意,以上做了几次初始化的边界处理,因为直接用 dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]),为了防止数组越界,只能先对前面的数做特殊处理。然后,可以发现这个dp的更新都是与前两个dp有关,优化一下,可以使用滚动数组,在每个时刻只需要存储前两间房屋的最高总金额。这样维护状态的就不是一整个dp数组了,而是前面两个类似前缀和的引用。
时间复杂度: O(n),空间复杂度: O(1)。
java
class Solution {
public int rob(int[] nums) {
int pre = 0, cur = 0, tmp;
for(int num : nums) {
tmp = cur;
cur = Math.max(pre + num, cur);
pre = tmp;
}
return cur;
}
}
动态处理的步骤,最重要的就是找到状态转移方程,当前状态可能不做更新,也可能与上一个状态有关。然后注意边界处理,用数组进行状态维护,若只与前几个数有关,也可以做空间优化。