Leetcode算法初学——动态规划算法“按摩师”

题目

 

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

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

题解

拿到题的第一想法其实是遍历,思路是两种情况,从n开始或者从n-1开始往前走,标志符是i,按摩师每工作一次就重置一次标志位,然后直接比较标志位i-2和i-3的大小,遍历整个数组,然后两种情况比较最大值

 

 1 class Solution {
 2 public:
 3     int massage(vector<int>& nums) {
 4         int n1=0,n2=0;//n1为从nums[0]开始遍历的结果,n2为从nums[1]开始遍历的结果
 5         int length=nums.size();
 6         for(int i=length-1;i>=0;)
 7         {
 8             if(i<=-1)
 9             {
10                 break;
11             }
12             n1=n1+nums[i];
13             if(nums[i-2]>=nums[i-3])
14             {
15                 i=i-2;
16             }
17             else if(nums[i-2]<nums[i-3])
18             {
19                 i=i-3;
20             }
21         }
22         for(int i=length-1;i>=0;)
23         {
24             if(i<=-1)
25             {
26                 break;
27             }
28             n2=n2+nums[i];
29             if(nums[i-2]>=nums[i-3])
30             {
31                 i=i-2;
32             }
33             else if(nums[i-2]<nums[i-3])
34             {
35                 i=i-3;
36             }
37         }
38         return max(n1,n2);
39     }
40 };

 

但是这种写法会导致数组访问越位,无法通过leetcode的AddressSanitizer检测,所以这种思路仅供参考,目前我还没有想到相对完善不会产生数组访问越位的情况,也只是用vs测试了示例中的三个例子,都通过了测试,但是没有更多的例子让我发现问题,所以仅供参考,不建议采用。用了很长时间考虑动态规划,但是没有接触过这种需要考虑间隔的问题,实在没有办法就参考了大神的题解https://leetcode-cn.com/problems/the-masseuse-lcci/solution/dong-tai-gui-hua-by-liweiwei1419-8/大神已经在题解里把这道题分析的很清楚了,我觉得需要注意的点就是考虑数组长度为0和1的情况,还有最后是要比较nums[n]的工作状态和非工作状态的取值大小,返回最大值,我本人是因为忘记限定数组长度的特殊范围被报错两次,这里就只贴代码了

 1 class Solution {
 2 public:
 3     int massage(vector<int>& nums) {
 4         int length=nums.size();
 5         if(length==0)
 6         {
 7             return 0;
 8         }
 9         if(length==1)
10         {
11             return nums[0];
12         }
13         int dp[length][2];
14         dp[0][0]=0;
15         dp[0][1]=nums[0];
16         for(int i=1;i<length;i++)
17         {
18             dp[i][0]=max(dp[i-1][0],dp[i-1][1]);
19             dp[i][1]=dp[i-1][0]+nums[i];
20         }
21         return max(dp[length-1][0],dp[length-1][1]);
22     }
23 };

成功通过测试样例:

 

 时间复杂度O(n),空间复杂度O(n)。

在这里记录一点自己的感想,本题难度仍为简单,我本来以为在已经有练习过几道题后,对于动态规划的题即使不是得心应手,费点时间也应该能自己独立ac,然而被现实教做人,每个算法不是表面上那么简单的,即使每道题解决的本质思路都相同,仍然会出现这样那样的情况让你无处下手,还是要多加练习,勉励自己。

 

posted @ 2020-06-20 18:33  菲特涅米  阅读(373)  评论(0编辑  收藏  举报