欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 健康 > 美食 > 力扣刷题之2555.两个线段获得的最多奖品

力扣刷题之2555.两个线段获得的最多奖品

2025/1/24 19:34:44 来源:https://blog.csdn.net/m0_75213259/article/details/142185795  浏览:    关键词:力扣刷题之2555.两个线段获得的最多奖品

题干描述

在 X轴 上有一些奖品。给你一个整数数组 prizePositions ,它按照 非递减 顺序排列,其中 prizePositions[i] 是第 i 件奖品的位置。数轴上一个位置可能会有多件奖品。再给你一个整数 k 。

你可以同时选择两个端点为整数的线段。每个线段的长度都必须是 k 。你可以获得位置在任一线段上的所有奖品(包括线段的两个端点)。注意,两个线段可能会有相交。

  • 比方说 k = 2 ,你可以选择线段 [1, 3] 和 [2, 4] ,你可以获得满足 1 <= prizePositions[i] <= 3 或者 2 <= prizePositions[i] <= 4 的所有奖品 i 。

请你返回在选择两个最优线段的前提下,可以获得的 最多 奖品数目。

示例 1:

输入:prizePositions = [1,1,2,2,3,3,5], k = 2
输出:7
解释:这个例子中,你可以选择线段 [1, 3] 和 [3, 5] ,获得 7 个奖品。

示例 2:

输入:prizePositions = [1,2,3,4], k = 0
输出:2
解释:这个例子中,一个选择是选择线段 [3, 3][4, 4] ,获得 2 个奖品。

题干解析

      这个题干要求我们在数轴上找到两个长度为k的线段,使得它们覆盖的奖品最多。线段之间可以重叠,但是为了获得最优解,我们需要计算出能够覆盖的奖品数量最大化的方案。

核心思路

      这道题我们打算使用动态规划法,理由如下:

这个问题的结构使得其每一步的最有解依赖于之前的计算结果,具体来说就是,若使用动态规划法可以帮助我们高效地解决两个非完全重叠的长度为k的线段所能覆盖的最大奖品数问题。

1.滑动窗口:
  • 我们可以使用两个滑动窗口来模拟两个长度为k的线段。每个滑动窗口代表一个线段,并计算线段内能够获得的奖品数量最大化的方案。
2.累积最大值:
  • 因为我们需要考虑两个不重叠线段的最优组合,因此我们可以维护一个动态规划数组dp,用来记录每一个位置之前的线段能够覆盖的最大奖品数量。
3.相交的处理:
  • 两个线段可能会有重叠的部分,因此我们要在动态规划的过程中考虑到线段的重叠情况,保证在取得两个线段时,总奖品数量最大。

详细解题思路

1.初始化:
  • 我们创建一个dp数组,dp[i]表示在第i位置之前,能够选择的最有线段所覆盖的奖品数量。
2.滑动窗口的运用:
  • 对于每个奖品位置prizePositions[i],我们将该位置作为一个活动窗口的右端点,计算出它能够覆盖的奖品数。
  • 我们不断调整滑动窗口的左端点left,确保滑动窗口的长度不超过k。
3.两个线段的最优选择:

        我们在动态规划过程中记录着两个线段的选择

  • 第一个线段通过滑动窗口计算当前的奖品数量。
  • 第二个线段则利用dp[left],表示当前线段左边能获得的最大奖品数量
  • 通过组合两个不重叠食物线段,计算当前的最大奖品数,并更新全局的最大值。
4.返回结果:
  • 最终返回两个线段能够覆盖的奖品的最大数量。

代码实现 

#include <stdio.h>
#include <stdlib.h>//计算在选择两个长度为k的线段的情况下,最多能获得的奖品数量
int maximizeWin(int* prizePositions, int prizePositionsSize, int k){//动态规划数组,用来记录当前线段之前的最大覆盖奖品数int* dp = (int*)malloc((prizePositionsSize + 1) * sizeof(int));//初始化dp数组for(int i = 0; i <= prizePositionsSize; ++i){dp[i] = 0;}int left = 0;//滑动窗口的左边界int maxCount = 0;//记录最大奖品数//遍历所有奖品的位置for(int right = 0; right < prizePositionsSize; ++right){//保证当前窗口内的长度不超过kwhile(prizePositions[right] - prizePositions[left] > k){left++;}//当前线段覆盖的奖品数int currentPrizes = right - left + 1;//使用动态规划保存两个线段不完全重叠的最大奖品数dp[right + 1] = dp[right] > currentPrizes ? dp[right] : currentPrizes;// 计算两个线段的最大奖品数(左边的最大 + 当前线段)int totalPrizes = dp[left] + currentPrizes;maxCount = maxCount > totalPrizes ? maxCount : totalPrizes;}// 释放动态分配的内存free(dp);return maxCount;
}

代码详解

1.动态规划数组dp:
  • 我们用dp[i]来记录在i位置之前,可以获得的最大奖品数。这是通过滑动窗口的计算得出的。
2.滑动窗口:
  • 我们使用两个指针left和right来实现滑动窗口。在每一步中,right向右扩展窗口,而left保证窗口的长度不超过k。
  • currentPrizes 记录当前窗口内能够获得的奖品数(也就是两个 leftright 之间的奖品数量)。
3.相交的处理:
  • 通过 dp[left] + currentPrizes,我们可以计算当前线段和前面不重叠线段的最大奖品数,并与 maxCount 比较以得到最终答案。
4.复杂度分析:
  • 时间复杂度:O(n),因为每个奖品位置只会被遍历一次。
  • 空间复杂度:O(n),因为我们使用了一个大小为 n 的数组 dp 来存储中间结果。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com