1. 题目解析
题目链接:面试题 17.16. 按摩师
这个问题的理解其实相当简单,只需看一下示例,基本就能明白其含义了。
2.算法原理
一、状态定义
在解决这类动态规划问题时,首先我们需要明确状态的定义。对于本题,我们定义两个状态数组来分别记录到达某个位置时,选择当前元素和不选择当前元素时的最长预约时长。
f[i]
:表示选择到第i
个位置时,且第i
个元素nums[i]
必须被选择的情况下的最长预约时长。g[i]
:表示选择到第i
个位置时,且第i
个元素nums[i]
不被选择的情况下的最长预约时长。
这样的状态定义有助于我们处理在每个位置上的选择问题,即选择当前元素或不选择当前元素。
二、状态转移方程
接下来,我们需要根据状态定义推导出状态转移方程。
-
对于
f[i]
:如果选择了第i
个元素,那么前一个位置i-1
的元素必然不被选择,因为不能连续选择两个元素。因此,f[i]
的值应该等于g[i-1]
(即不选择第i-1
个元素时的最长预约时长)加上当前元素的值nums[i]
。即:f[i] = g[i - 1] + nums[i]
。 -
对于
g[i]
:如果不选择第i
个元素,那么前一个位置i-1
的元素可以选择也可以不选择。因此,g[i]
的值应该等于前一个位置选择或不选择两种情况下的最长预约时长的较大值。即:g[i] = max(f[i - 1], g[i - 1])
。
三、初始化
对于动态规划问题,合理的初始化是解决问题的关键。对于本题,我们根据题目要求和状态定义进行初始化。
- 初始化
f[0]
为nums[0]
,因为当只有一个元素时,必然选择该元素,其最长预约时长即为该元素的值。 - 初始化
g[0]
为0,因为当只有一个元素时,如果不选择该元素,则最长预约时长为0。
四、填表顺序
根据状态转移方程,我们可以从左往右依次填充f
和g
两个数组。因为每个位置的状态依赖于前一个位置的状态,所以必须按照从左到右的顺序进行填表。
五、返回值
最后,根据状态定义,我们需要返回选择到最后一个位置时的最长预约时长,即max(f[n-1], g[n-1])
。因为在最后一个位置,我们可以选择该位置的元素也可以不选择,所以取两种情况下的较大值作为最终结果。
3.代码编写
class Solution {
public:int massage(vector<int>& nums) {int n = nums.size();if(n == 0) return 0;vector<int> f(n), g(n);f[0] = nums[0];for (int i = 1; i < n; i++) {f[i] = g[i - 1] + nums[i];g[i] = max(f[i - 1], g[i - 1]);}return max(f[n - 1], g[n - 1]);}
};
The Last
嗯,就是这样啦,文章到这里就结束啦,真心感谢你花时间来读。
觉得有点收获的话,不妨给我点个赞吧!
如果发现文章有啥漏洞或错误的地方,欢迎私信我或者在评论里提醒一声~