LeetCode热题(JS版) - 198. 打家劫舍

83 阅读1分钟

题目描述

给定一个数组,表示房屋中的每个房间里的钱。你不能同时抢劫相邻的房屋,否则会触发警报。计算能够抢劫到的最大数量。

示例

示例1:

Input: [1,2,3,1]
Output: 4
Explanation: 抢劫第1个房间(金额为1),然后抢劫第3个房间(金额为3)。总共的收益为1+3=4。

示例2:

Input: [2,7,9,3,1]
Output: 12
Explanation: 抢劫第1个房间(金额为2),然后抢劫第3个房间(金额为9),最后抢劫第5个房间(金额为1)。总共的收益为2+9+1=12。

解法

这道题可以使用动态规划来解决,我们可以定义dp[i]表示抢劫前i个房间所能获得的最大利润。那么对于第i个房间,我们只有两种选择:

  • 不抢这个房间,那么当前最大利润就是前(i-1)个房间所能获得的最大利润,即dp[i-1];
  • 抢这个房间,那么当前最大利润就是前(i-2)个房间所能获得的最大利润加上当前房间中的钱数,即dp[i-2]+nums[i-1]。

因此,我们可以得到状态转移方程:dp[i] = max(dp[i-1], dp[i-2]+nums[i-1])。最终的答案就是dp[n],其中n为数组的长度。

代码

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

时间复杂度

遍历整个数组需要花费O(n)O(n)的时间,对于每个位置,我们只需要进行常数级别的操作,因此总的时间复杂度为O(n)O(n)