Maximize Win From Two Segments
Maximize Win From Two Segments
There are some prizes on the X-axis. You are given an integer array prizePositions that is sorted in non-decreasing order, where prizePositions[i] is the position of the ith prize. There could be different prizes at the same position on the line. You are also given an integer k .
You are allowed to select two segments with integer endpoints. The length of each segment must be k . You will collect all prizes whose position falls within at least one of the two selected segments (including the endpoints of the segments). The two selected segments may intersect.
- For example if k = 2 , you can choose segments [1, 3] and [2, 4] , and you will win any prize i that satisfies 1 <= prizePositions[i] <= 3 or 2 <= prizePositions[i] <= 4 .
Return the maximum number of prizes you can win if you choose the two segments optimally.
Example 1:
Input: prizePositions = [1,1,2,2,3,3,5], k = 2 Output: 7 Explanation: In this example, you can win all 7 prizes by selecting two segments [1, 3] and [3, 5].
Example 2:
Input: prizePositions = [1,2,3,4], k = 0 Output: 2 Explanation: For this example, one choice for the segments is [3, 3] and [4, 4], and you will be able to get 2 prizes.
Constraints:
- prizePositions is sorted in non-decreasing order.
解题思路
比赛的时候贪心思路搞错了,一直在wa,然后对着个样例看了半天都不知道错了哪里。
一开始的贪心思路是想着线段的其中一个端点一定要覆盖到礼物,然后右端点取到长度限制,这里的贪心思路还是对的。然后我就理所应当的认为下一条线段的左端点应该从上一条线段的右端点的右边开始(不要重合),这样做的后果是把序列分成了连续的若干段,再对这若干段按照能够取到的礼物数量从大到小排序,最后取排序结果的前两个作为答案。

class Solution { public: int maximizeWin(vector<int>& prizePositions, int k) { int n = prizePositions.size(); vector<int> p(1); for (int i = 0; i < n; i++) { int j = i + 1; while (j < n && prizePositions[j] - prizePositions[i] <= k) { j++; } p.push_back(j - i); i = j - 1; } sort(p.begin(), p.end(), greater<int>()); return p[0] + p[1]; } };
一开始死都没发现不对的地方,后面看了别人的题解才知道这种做法是有问题的。
首先容易贪心想到线段端的某个端点(这里假设是左端点)如果包含礼物,那么这条线段能够覆盖的礼物会更多。同时选择的两个线段没有相交的情况能够覆盖到的礼物会更多。
接着我们通过双指针来预处理得到以为左端点所能够覆盖到的最大礼物数量,得到数组。再预处理得到以为右端点所能够覆盖到的最大礼物数量,得到数组。然后枚举所有,作为第二条线段的左端点,此时第一条线段的右端点应该选择,因此还需要对数组求前缀最大值。那么这种情况的所能覆盖到的最大礼物数量为,在枚举的过程中对所有情况取个最大值。
AC代码如下:
1 class Solution { 2 public: 3 int maximizeWin(vector<int>& prizePositions, int k) { 4 int n = prizePositions.size(); 5 vector<int> l(n + 1), r(n + 1); 6 for (int i = 1, j = 1; i <= n; i++) { 7 while (prizePositions[i - 1] - prizePositions[j - 1] > k) { // 右端点 8 j++; 9 } 10 r[i] = i - j + 1; 11 } 12 for (int i = 1; i <= n; i++) { // 对r数组求前缀最大值 13 r[i] = max(r[i], r[i - 1]); 14 } 15 for (int i = n, j = n; i; i--) { 16 while (prizePositions[j - 1] - prizePositions[i - 1] > k) { // 左端点 17 j--; 18 } 19 l[i] = j - i + 1; 20 } 21 int ret = 0; 22 for (int i = 1; i <= n; i++) { 23 ret = max(ret, l[i] + r[i - 1]); 24 } 25 return ret; 26 } 27 };
参考资料
two pointers & 枚举:https://leetcode.cn/problems/maximize-win-from-two-segments/solution/two-pointers-mei-ju-by-tsreaper-bui2/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17093504.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效