分享

477,动态规划解按摩师的最长预约时间

 数据结构和算法 2023-06-10 发布于上海

Life is a collection of moments. The idea is to have as many good ones as you can.

生命由一系列的瞬间组成。宗旨是尽可能地拥有快乐的瞬间。

问题描述



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

示例 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[length][2],其中dp[i][0]表示第i+1(因为数组下标是从0开始的,所以这里是i+1)个预约没有接的最长总预约时间,dp[i][1]表示的是第i+1个预约接了的最长总预约时间。那么我们找出递推公式

1,dp[i][0]=max(dp[i-1][0],dp[i-1][1])

他表示如果第i+1个没有接,那么第i个有没有接都是可以的,我们取最大值即可。

2,dp[i][1]=dp[i-1][0]+nums[i]

他表示的是如果第i+1个接了,那么第i个必须要没接,这里nums[i]表示的是第i+1个预约的时间。

递推公式找出来之后我们再来看下边界条件,第一个预约可以选择接,也可以选择不接,所以

  • dp[0][0]=0,第一个没接

  • dp[0][1]=nums[0],第一个接了。

最后再来看下代码

 1public int massage(int[] nums{
2    //边界条件判断
3    if (nums == null || nums.length == 0)
4        return 0;
5    int length = nums.length;
6    int[][] dp = new int[length][2];
7    dp[0][0] = 0;//第1个没接
8    dp[0][1] = nums[0];//第1个接了
9    //从第2个开始判断
10    for (int i = 1; i < length; i++) {
11        //下面两行是递推公式
12        dp[i][0] = Math.max(dp[i - 1][0], dp[i - 1][1]);
13        dp[i][1] = dp[i - 1][0] + nums[i];
14    }
15    //最后取最大值即可
16    return Math.max(dp[length - 1][0], dp[length - 1][1]);
17}

动态规划优化



上面定义了一个二维数组,但每次计算的时候都只是用二维数组的前一对值,在往前面的就永远使用不到了,这样就会造成巨大的空间浪费,所以我们可以定义两个变量来解决,来看下代码

 1public int massage(int[] nums{
2    //边界条件判断
3    if (nums == null || nums.length == 0)
4        return 0;
5    int length = nums.length;
6    int dp0 = 0;//第1个没接
7    int dp1 = nums[0];//第1个接了
8    //从第2个开始判断
9    for (int i = 1; i < length; i++) {
10        //防止dp0被修改之后对下面运算造成影响,这里
11        //使用一个临时变量temp先把结果存起来,计算完
12        //之后再赋值给dp0.
13        int temp = Math.max(dp0, dp1);
14        dp1 = dp0 + nums[i];
15        dp0 = temp;
16    }
17    //最后取最大值即可
18    return Math.max(dp0, dp1);
19}

总结



首先这里都是正规的按摩师,使用动态规划是最容易解决的,只要找准递推公式,基本上也没什么难度。

465. 递归和动态规划解三角形最小路径和

430,剑指 Offer-动态规划求正则表达式匹配

423,动态规划和递归解最小路径和

413,动态规划求最长上升子序列

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多