你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。
给定一个代表每个房屋存放金额的非负整数数组,计算你 不触动警报装置的情况下 ,一夜之内能够偷窃到的最高金额。
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 偷窃 1 号房屋 (金额 = 1) ,然后偷窃 3 号房屋 (金额 = 3)。
偷窃到的最高金额 = 1 + 3 = 4 。
示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 偷窃 1 号房屋 (金额 = 2), 偷窃 3 号房屋 (金额 = 9),接着偷窃 5 号房屋 (金额 = 1)。
偷窃到的最高金额 = 2 + 9 + 1 = 12 。
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 400
题解:
/**
* @description: 动态规划 TC:O(n^2) SC:O(n)
* @param {*} nums 给定非负数组
*/
function dp(nums){
/**
* 本方案使用动态规划,对于数n而言,其
* 最大组合为:
* 数n+Max(数n-2最大组合数,数n-3最大组合数....数0最大组合数)
* 例如:
* 数组: 3 2 8 9 7 1
* 最大组合数: 3 2 11 12 18 13
* 以此为状态方程编写代码即可
*/
// 如何数组长度为1,直接返回唯一元素即可
if(nums.length==1)return nums[0]
// 遍历数组元素
for(let i=0;i<nums.length;i++){
let max=0
// 获得之前元素的最大组合数
// Max(数n-2最大组合数,数n-3最大组合数....数0最大组合数)
for(let j=i-2;j>=0;j--)max=Math.max(max,nums[j])
// 计算当前元素最大组合数
nums[i]+=max
}
// 返回值
return Math.max(nums[nums.length-1],nums[nums.length-2])
}
/**
* @description: 动态规划优化 TC:O(n) SC:O(1)
* @param {*} nums 给定非负数组
*/
function dpOptimization(nums){
/**
* 上述DP使用了数组存储结果,并且每次都会重复遍历
* 获取之前元素的最大组合数,为此我们可以使用滚动
* 数组进行优化,在每个时刻只需要存储前两个元素的
* 最大组合数即可。
*/
// 如何数组长度为1,直接返回唯一元素即可
if(nums.length==1)return nums[0]
// 获取前两个元素的最大组合数
let first=nums[0],second=Math.max(nums[0], nums[1]);
// 遍历数组
for(let i=2;i<nums.length;i++){
let temp=second
// 与前二最大组合数相加计算当前元素最大组合数,与前一元素比较
// 以获最大组合数
second=Math.max(first+nums[i],second)
first=temp
}
// 返回结果
return second
}