leetcode--打家劫舍

打家劫舍

动态规划的又一道基础题,先分析问题子结构,再列公式。

问题描述

小偷进行偷窃,不能偷窃相邻的两个房间,不然会触发报警,请问怎样才能窃取到最大的金额。

金额数字用数组表示

[1, 2, 3, 1]

问题分析

  • 要首先看一个问题能不能由他的子问题进行解决

    • 可以:能用动态规划;不可以:不能用动态规划解决。
  • 假设一共有n个房间,求偷n个房间的最大值

  • 最后一个房间只有偷和不偷两种方式

    • 偷:f(n) = f(n-2) + n
    • 不偷: f(n) = f(n-1)
  • 所以,n个房间的最大值

    • f(n) = max(f(n-2) + n, f(n-1))
  • 基本思想如上所述,该问题可以由动态规划算法完成。

let rob = function(nums) {
  let len = nums.length;

  if(len === 0)
  return 0;

  if(len === 1)
  return nums[0];

  if(len === 2)
  return Math.max(nums[0], nums[1]);

  let dp = []; // 用数组来记录每到k个房间的最大值
  dp[0] = 0;
  dp[1] = nums[0];
  dp[2] = Math.max(nums[0], nums[1])
  for(let i = 3; i <= len; i++) {
    dp[i] = Math.max(dp[i-1], dp[i-2] + nums[i-1]); // 用刚才推算出来的算法来进行计算
  }

  return dp[len]; //返回最后的值
}

仔细观察可以发现,算到n个房间只需要n-1和n-2的最大值就可以了,也就是我们只需要保存前面两个情况的最大值。

就可以算出n个房间的最大值,所以我们只需要利用变量重复赋值就可以了,不需要用到数组。

这样我们的空间复杂度就由O(N)变成了O(1)。

let rob = function(nums) {
  let len = nums.length;

  if(len === 0)
  return 0;

  if(len === 1)
  return nums[0];

  if(len === 2)
  return Math.max(nums[0], nums[1]);

  // temp记录每次到i的结果
  let temp;
  // 利用prev2记录i-2的最大值,prev1记录i-1的最大值。
  let prev2 = nums[0];
  let prev1 = Math.max(nums[0], nums[1])
  for(let i = 3; i <= len; i++) {
    temp = Math.max(prev1, prev2 + nums[i-1]);
    prev2 = prev1;
    prev1 = temp;
  }

  return temp;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值