题目描述
打家劫舍思路
在这个问题中,假设只有一房屋,则偷窃该房屋,如果有两间房屋,由于不能偷相邻的房屋,所以返回两间房屋中最大的金额。 如果房屋数量大于两间, 那么如何计算呢,假设我要偷第 4 间房屋, 有两种偷法 , 是不是只能偷第1、2 或者 第2、4间, 比比这两种偷法,谁的总金额最大
那么对于 k 间房间(k>2), 有个选项:
- 如果偷 k 间房间的话,那么金额为 k-2 间房屋的最高金额之和与第 k 间房屋的金额之和
- 如果不偷 k 间房间的话,那么金额为 k-1 房屋的最高金额之和
- 看看这两种哪个比较大,哪个大就是最终结果 用 dp[i] 来表示第 i 间房间能够偷窃的最高总金额,那么
状态转移方程
dp[i] = max(dp[i-2] + num[i], dp[i-1])
边界条件为
dp[0]=nums[0] 只有一间房屋,则偷窃该房屋
dp[1]=max(nums[0],nums[1]) 只有两间房屋,选择其中金额较高的房屋进行偷窃
代码示例
空间复杂度 O(n) 解法
function rob(nums: number[]): number {
let n = nums.length;
if (n == 1) return nums[0];
let dp = new Array(n);
dp[0] = nums[0];
dp[1] = Math.max(nums[0], nums[1]);
for (let i = 2; i < n; i++) {
dp[i] = Math.max(dp[i - 2] + nums[i], dp[i - 1]);
}
return dp[n - 1]
};
- 时间复杂度: O(n) , n 是数组的长度
- 空间复杂度: O(n), n 是数组的长度
空间复杂度 O(1) 解法,使用滚动数组
function rob(nums: number[]): number {
let n = nums.length;
if (n == 1) return nums[0];
let first = nums[0], second = nums[1];
let temp = 0
for (let i = 2; i < n; i++) {
temp = second;
second = Math.max(first + nums[i], second);
first = temp;
}
return second
};
- 时间复杂度: O(n) , n 是数组的长度
- 空间复杂度: O(1), 仅仅使用了常量作为临时变量