两个线段获得的最多奖品
难度:
标签:
题目描述
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 satisfies1 <= prizePositions[i] <= 3
or2 <= 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 get2
prizes.
Constraints:
1 <= prizePositions.length <= 105
1 <= prizePositions[i] <= 109
0 <= k <= 109
prizePositions
is sorted in non-decreasing order.
代码结果
运行时间: 67 ms, 内存: 26.9 MB
/*
* 思路:
* 1. 使用流来处理数组。
* 2. 计算以每个位置为起点的长度为k的线段内的奖品数量。
* 3. 使用流和滑动窗口来计算在不重叠的情况下,两个线段内的最大奖品数量。
* 4. 返回最大值。
*/
import java.util.stream.IntStream;
public class Solution {
public int maxPrizes(int[] prizePositions, int k) {
int n = prizePositions.length;
int[] count = IntStream.range(0, n).map(i -> {
int j = i;
while (j < n && prizePositions[j] <= prizePositions[i] + k) {
j++;
}
return j - i;
}).toArray();
return IntStream.range(0, n).flatMap(i -> IntStream.range(i + count[i], n).map(j -> count[i] + count[j])).max().orElse(0);
}
}
解释
方法:
这个题解采用的是一种贪心加滑动窗口的方法。首先,特殊情况判断:如果两个长度为k的线段加上中间至少一个单位的间隔仍然小于整个奖品分布的跨度,则说明所有奖品都可以在两个线段内被覆盖,直接返回所有奖品的数量。在一般情况下,使用滑动窗口来确定每个位置结尾的线段可以覆盖的最多奖品数量,并记录下来。同时,通过维护一个pre数组,记录以每个位置结尾时前一个线段可以覆盖的最多奖品数量。最终,通过比较,找到两个线段可以覆盖的最大奖品数量。
时间复杂度:
O(n)
空间复杂度:
O(n)
代码细节讲解
🦆
请问在计算两个线段覆盖的最大奖品数时,为什么可以通过简单地将两个线段的奖品数相加得到结果?是否需要考虑两个线段的重叠部分?
▷🦆
在题解中提到的特殊情况`如果两个长度为k的线段加上中间至少一个单位的间隔仍然小于整个奖品分布的跨度`,这里的逻辑是否有误?应该是`小于等于`还是`小于`整个奖品分布的跨度?
▷🦆
题解中使用的滑动窗口方法,如何确保在移动左指针时,不会错过某些可能的最优解?
▷🦆
在更新`pre`数组时,为什么选择`pre[right + 1] = max(pre[right], right - left + 1)`,这里的`right - left + 1`具体代表什么含义?
▷