【Leetcode】198. 打家劫舍

32 阅读1分钟

leetcode-198.png

这是一题比较典型的动态规划问题。
相邻的节点不能访问,求最后如果获取到的总值最大。
那么这里就有一个基础的问题了,如果此时想在i节点获取到最大的值

由于不能偷取相邻的房屋,因此对于第 i 个房子,我们有两个选择:

  1. 偷这间房子 —— 那就不能偷第 i - 1 间房,只能加上 dp[i - 2]
  2. 不偷这间房子 —— 那就继承上一个最大收益 dp[i - 1]

因此,我们可以列出状态转移方程: 那么应该是 nums[i] + dp[i-2]dp[i-1] 相比较
此时可以得到状态转移方程

// dp[n] 来记录在某个节点上可以获取到的最大值
dp[i] = Math.max(dp[i-2] + nums[i], dp[i-1])

dp 数组

var rob = function (nums) {
    let n = nums.length;
    if (n === 1) return nums[0];
    if (n === 2) return Math.max(nums[0], nums[1]);
    let dp = new Array(n).fill(0);
    dp[0] = nums[0];
    dp[1] = Math.max(nums[0], nums[1]);
    for (let i = 2; i < n; ++i) {
        dp[i] = Math.max(nums[i] + dp[i - 2], dp[i - 1]);
    }
    return dp[n-1];
};

时间复杂度:O(n)
空间复杂度:O(n)

dp 常数存储前面两个状态,所以也不用存储整个数组

因为只需要

var rob = function (nums) {
    let n = nums.length;
    if (n === 1) return nums[0];
    if (n === 2) return Math.max(nums[0], nums[1]);
    let dp = new Array(n).fill(0);
    prev1 = nums[0];
    prev2 = Math.max(nums[0], nums[1]);
    for (let i = 2; i < n; ++i) {
        let current = Math.max(prev1 + nums[i], prev2);
        prev1 = prev2;
        prev2 = current;
    }
    return prev2;
};

时间复杂度:O(n)
空间复杂度:O(1)