每日一题——两个线段获得的最多奖品

236 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 9 天,点击查看活动详情


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 个奖品。

 

提示:

  • 1 <= prizePositions.length <= 105
  • 1 <= prizePositions[i] <= 109
  • 0 <= k <= 109
  • prizePositions 有序非递减。

不难看出这道题目需要用到双指针,如果是一个线段的话,是比较容易想到如何得到最大的值的,我们只需要保持两个指针之间的元素的差值是小于等于 k 的就可以。

但是题目要求的是两个线段,在两个线段的条件下想要求得两个线段的最大值,需要确保两个线段都尽可能的取到最大值。

对于第一条线段,我们可以使用一个数组记录下来每个位置处,我们可以取到的最大值,这样我们可以在求第二条线段时,找到第二条线段的值的同时,取left下标前的第一条线段最大值,即可得到最终答案。

class Solution {
    public int maximizeWin(int[] prizePositions, int k) {
        int n = prizePositions.length;
        int ans = 0;
        int[] pre = new int[n + 1];
        pre[0] = 0;
        for(int left = 0, right = 0; right < n; right++) {
            while(prizePositions[right] - prizePositions[left] > k) {
                left++;
            }
            pre[right + 1] = Math.max(pre[right], right - left + 1);
        }
        for(int left = 0, right = 0; right < n; right++) {
            while(prizePositions[right] - prizePositions[left] > k) {
                left++;
            }
            ans = Math.max(ans, right - left + 1 + pre[left]);
        }
        return ans;
    }
}

如果你有其他的思路或者更好的解法,亦或者你发现了文章出现了错误或有不足,欢迎在评论区和我交流,我看到了一定会回复。

写文章不易,如果你觉得文章对你有帮助,麻烦点一下点赞、收藏,你的支持是我写文章的最大动力!