最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 【魅力算法】“按摩师/打家劫舍”-动态规划、滚动数组思想实现 |刷题打卡

    正文概述 掘金(GeekQiaQia)   2021-03-11   635

    题目描述

    一个有名的按摩师会收到源源不断的预约请求,每个预约都可以选择接或不接。
    在每次预约服务之间要有休息时间,因此她不能接受相邻的预约。给定一个预约请求序列,
    替按摩师找到最优的预约集合(总预约时间最长),返回总的分钟数。
    
    注意:本题相对原题稍作改动
    
     
    
    示例 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。
    
    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/the-masseuse-lcci
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
    
    

    解题思路

    动态规划

    题目理解

    按摩师对于每一个预约请求:

    • 可以接受预约;
    • 可以不接受预约;
    • 且不能接受相邻的预约请求;
    • 最后需要得出请求序列总预约时间最长

    举例1:预约序列为 [1,2,3,1]有以下几种可能:

    • 假设我们接受1号预约,则不能接受2号预约;
      • 为了总预约时长最长;
      • 在3号/4号预约中,选择3预约;
      • 总时长为:1+3=4;
    • 假设我们不接受1号预约,则可选择接受2号/3号预约;
      • 假设选择2号预约,则必须选择4号预约:总时长为:2+1=3;
      • 假设选择3号预约,由于不接受相邻预约,则后面的预约不接受;总时长为:3

    综上:最佳选择为:1+3=4;

    标准动态规划问题:

    • 定义状态:dp[i]表示:序列中 0 至 i 区间,接受预约请求最大的时长;
    • 状态转移方程:
      • 接受预约:则前一天一定休息,由于状态dp[i-1]定义涵盖了i-1这一天接受预约的情况,
        • 状态转移:dp[i]的状态一定由 dp[i-2]+nums[i] 转移而来;
      • 不接受预约:则前一天可以休息,也可以不休息,
        • 状态转移:dp[i]的状态由 下标为 i-1的 dp[i-1]状态转移而来
      • 状态转移方程为:dp[i]=max(dp[i-2]+nums[i],dp[i-1]);
    • 初始化:
      • 由状态转移方程可知,下标最小为 i-2;
      • 因此需要初始化dp[0],dp[1],从dp[2]开始计算,即:第三天开始动态规划;
      • 考虑到需接受预约请求最大的时长:
        • dp[0]:只有一天的时候,必须接受预约;
          • dp[0]=nums[0];
        • dp[1]:前两天,由于不能同时接受预约,因此最优解为:
          • dp[1]=max(nums[0],nums[1]);

    代码

    /**
     * @param {number[]} nums
     * @return {number}
     */
    var massage = function(nums) {
    
     let len=nums.length;
     if(len==0){
         return 0;
     }
     if(len==1){
         return nums[0]
     }
     // 定义状态:dp[i]表示:0 至 i区间,接受预约请求最大的时长;
      let dp=[len];
      dp[0]=nums[0];
      dp[1]=Math.max(nums[0],nums[1]);
      for(let i=2;i<len;i++){
          // 今天是否接受预约,选则一个时间最长的
          dp[i]=Math.max(dp[i-1],dp[i-2]+nums[i]);
      }
      return dp[len-1]
      
    };
    

    解题思路

    滚动数组思想

    • 由于只涉及到dp[i]、dp[i-1]、dp[i-2];
    • 当i=2时:
      • dp[i%3]=Math.max(dp[(i-1)%3],dp[(i-2)%3]+nums[i]);
        • dp[2%3]=Math.max(dp[(2-1)%3],dp[(2-2)%3]+nums[i]);
        • dp[2]=Math.max(dp[1],dp[0]+nums[i]);
    • 使用3个变量滚动完成计算,将空间优化到常数级别;
    /**
     * @param {number[]} nums
     * @return {number}
     */
    var massage = function(nums) {
    
     let len=nums.length;
     if(len==0){
         return 0;
     }
     if(len==1){
         return nums[0]
     }
     // 定义状态:dp[i%3]表示:0 至 i区间,接受预约请求最大的时长;
      let dp=[3];
      dp[0]=nums[0];
      dp[1]=Math.max(nums[0],nums[1]);
      for(let i=2;i<len;i++){
          // 今天是否接受预约,选则一个时间最长的
          dp[i%3]=Math.max(dp[(i-1)%3],dp[(i-2)%3]+nums[i]);
      }
      return dp[(len-1)%3]
      
    };
    

    起源地下载网 » 【魅力算法】“按摩师/打家劫舍”-动态规划、滚动数组思想实现 |刷题打卡

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元