浅聊一下
最近面试,碰到最多的算法题就是动态规划,很多同学都不知道动态规划的题目应该如何下手,今天就来讲讲leetcode上的一道原题(面试题 17.16. 按摩师 - 力扣(LeetCode))...
面试了这么多天,觉得一个人的力量还是太过薄弱,如果你和我一样有向前冲的勇气,欢迎掘友们私聊我交流面经(wechat: LongLBond)
按摩师
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
首先我们拿到题目,怎么判断是否要使用动态规划来解决呢?来看看题目要求我们求什么...
替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
看到 最优、最大、最小 的最值问题,我们应该第一时间想到用动态规划来解决...当决定使用动态规划来解决问题以后,就该从武器库中掏出我们的 动规五部曲 出来一阵突突了...
动规五部曲
- 定义状态
第一步我们要理解题意,找到我们要设置的dp[ ]到底代表什么...来看题,我们要求得总预约时间最长的集合,不难想到dp[i]应该代表到第i天的总预约最大时长
let dp = new Array(nums.length+1).fill(0);
- 找到状态转移方程
根据题目给出的条件来列出状态转移方程
每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约
在这里有两种情况
- 今天约
如果今天约,那么昨天必定没约...所以到今天为止,最大预约时长为前天的最大预约时长加上今天
dp[i] = dp[i-2] + nums[i]
- 今天不约
如果今天不约,那么到今天为止,最大预约时长就等于昨天的最大预约时长
dp[i] = dp[i-1]
- 整合
我们需要求得到今天的最大预约时长,所以我们应该选择 今天约 和 今天不约 的最大值
dp[i] = Math.max(dp[i-1],dp[i-2]+nums[i])
这就是我们求得的 动态转移方程
- 初始化
在上面我们求得了 动态转移方程 ,发现每个dp[i]的值都依赖于前面的值,所以我们要初始化dp[0]的值...第1天的时候,毫无疑问,此时最大预约时长为nums[0],第1天的时候,同样的毫无疑问,最大预约时长为 第一天和第二天之间的最大值 dp[1] = Math.max(nums[0],nums[1]),到此初始化完成...
- 迭代
到这里的逻辑就十分简单了,通过循环求得每一天的最大预约时长...
js
for (let i = 2; i < nums.length; i++) {
dp[i] = Math.max(dp[i-1], nums[i] + dp[i-2]);
}
- 返回结果
最后将nums数组作为函数的参数,dp[nums.length-1]就是我们要的最大预约时长...
return dp[nums.length-1]
完整代码
js
var massage = function(nums) {
if(nums.length == 0){
return 0
}
let dp = new Array(nums.length+1).fill(0);
dp[0] = nums[0];
dp[1] = Math.max(dp[0], nums[1]);
for (let i = 2; i < nums.length; i++) {
dp[i] = Math.max(dp[i-1], nums[i] + dp[i-2]);
}
return dp[nums.length-1];
};
结尾
面试很大概率会碰到动态规划的题目,遇到不要紧张,冷静分析就能拿下...