按摩师(题号不确定)
题目
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
注意:本题相对原题稍作改动
示例 1:
输入: [1,2,3,1]
输出: 4
解释: 选择 1 号预约和 3 号预约,总时长 = 1 + 3 = 4。
示例 2:
输入: [2,7,9,3,1]
输出: 12
解释: 选择 1 号预约、 3 号预约和 5 号预约,总时长 = 2 + 9 + 1 = 12。
示例 3:
输入: [2,1,4,5,3,1,1,3]
输出: 12
解释: 选择 1 号预约、 3 号预约、 5 号预约和 8 号预约,总时长 = 2 + 4 + 3 + 3 = 12。
解释
经典动态规划,比较简单的一题,用来回忆动态规划再合适不过了。
这题和买卖股票需要休息一天有点类似,不过更加简单一点,不需要做减法处理,直接取值相加即可。
因为需要休息一天,所以DP状态可以为:
DP[i][当天不预约] = Math.max(DP[i - 1][当天预约], DP[i - 1][当天不预约])
DP[i][当天预约] = DP[i - 1][当天不预约] + 当天预约时间
或者可以转化成单个数组,这里初始值就需要多赋值一次了,循环从2开始,可以直接确定当天的最多预约时间。
DP[i] = Math.max(DP[i - 2] + 当天预约时间, DP[i - 1])
两种方法都可以,差别不大。
自己的答案(双数组)
var massage = function(nums) {
var len = nums.length
arrHas = new Array(len)
arrNone = new Array(len)
if (!len) return 0
arrHas[0] = nums[0]
arrNone[0] = 0
for (let i = 1; i < len; i++) {
arrHas[i] = arrNone[i - 1] + nums[i]
arrNone[i] = Math.max(arrHas[i - 1], arrNone[i - 1])
}
return Math.max(arrHas[len - 1], arrNone[len - 1])
};
也是比较简单,arrHas
数组表示当天预约的情况,arrNone
表示当天休息的情况,最后去二者最后一个元素的最大值即可。
自己的答案(降维)
var massage = function(nums) {
var len = nums.length
order = nums[0]
rest = 0
if (!len) return 0
for (let i = 1; i < len; i++) {
[order, rest] = [rest + nums[i], Math.max(order, rest)]
}
return Math.max(order, rest)
};
通过上面的答案可以得出,其实只需要记录前一天休息和预约的两种不同状态即可,所以直接提取成两个变量,order
代表前一天预约了,rest
代表前一天休息了。
每次循环时使用解构赋值来更新order
和rest
,省去了中间步骤的情况。
使用解释里面的第二个DP公式也可以,只是计算当天的公式需要简单变化下,问题不大。
PS:想查看往期文章和题目可以点击下面的链接:
这里是按照日期分类的👇
经过有些朋友的提醒,感觉也应该按照题型分类
这里是按照题型分类的👇
有兴趣的也可以看看我的个人主页👇