第四题——面试题 17.16. 按摩师

动态规划(简单)

前言

纯个人笔记,记录自己动态规划学习次序与题目(大多为力扣的题目)方便复习查找。
本人学习使用的是c++,纯纯纯新手有写的不对的地方,非常欢迎来提醒
对于我这个新手来说大部分的题是很难做出来,肯定会借鉴相应的题解和解析,如果有争议,我会删除

第一题

题目

面试题 17.16. 按摩师
一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。

注意:本题相对原题稍作改动

示例 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。

本题的意思是,例如[1,2,3,1],代表着4天,第一天有1个小时,第二天有2个小时,第三天有3个小时,第四天有1个小时,但是在不能连续选择的情况下,时间最长=1+3=4,选第一天和第三天。

代码

class Solution {
public:
    int massage(vector<int>& nums) 
    {
        if(nums.empty()) return 0;//考虑特殊情况,为空时,返回0
        if(nums.size()==1) return nums[0];//nums长度为1,只有一个元素,则返回当前元素即可

        int length=nums.size();
        vector<int> dp(length);//定义一维数组
        dp[0]=nums[0];
        dp[1]=max(nums[0],nums[1]);

        for(int i=2;i<length;i++)
        {
            dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
        }
        return dp[length-1];
    }
};

解释

1、dp的定义
因为替按摩师找到最优的预约集合 (总预约时间最长) 所以dp[i]代表在考虑下标 i (包含 i ) 的,最大时间。
2、递推公式
dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
在下标 i 的时候可以考虑两种情况,选不选下标 i 的那天。
(1)如果选下标 i 的那天,则 i 的前一天不能再选,要从第 i-2 开始考虑 (因此她不能接受相邻的预约) ,就是在 i-2 之前的最大时间加上 i 的时间->dp[i-2]+nums[i];
(2)如果不选下标 i 的那天,则 i 的前一天能选,要从第 i-1 开始考虑,就是 i-1 之间的最大时间->dp[i-1];
因为是两种情况,所以两者之间取最大值->max(dp[i-2]+nums[i],dp[i-1]);
3、dp初始化
因为递推公式是由 dp[i-1] 和 dp[i-2] 决定的,所以初始化 dp[0] 和 dp[1] 。
dp[0]是考虑下标 0 及之前的最大时间->dp[0]=nums[0];
dp[1]表示下标为 1 及之前的最大时间,取两个数的最大值->dp[1]=max(nums[0],nums[1]);

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值