给你一个下标从 0 开始的二维整数数组 flowers
,其中 flowers[i] = [starti, endi]
表示第 i
朵花的 花期 从 starti
到 endi
(都 包含)。同时给你一个下标从 0 开始大小为 n
的整数数组 people
,people[i]
是第 i
个人来看花的时间。
请你返回一个大小为 n
的整数数组 answer
,其中 answer[i]
是第 i
个人到达时在花期内花的 数目 。
示例 1:
输入:flowers = [[1,6],[3,7],[9,12],[4,13]], people = [2,3,7,11] 输出:[1,2,2,2] 解释:上图展示了每朵花的花期时间,和每个人的到达时间。 对每个人,我们返回他们到达时在花期内花的数目。
示例 2:
输入:flowers = [[1,10],[3,3]], people = [3,3,2] 输出:[2,2,1] 解释:上图展示了每朵花的花期时间,和每个人的到达时间。 对每个人,我们返回他们到达时在花期内花的数目。
提示:
1 <= flowers.length <= 5 * 10^4
flowers[i].length == 2
1 <= starti <= endi <= 10^9
1 <= people.length <= 5 * 10^4
1 <= people[i] <= 10^9
提示 1
Notice that for any given time t, the number of flowers blooming at time t is equal to the number of flowers that have started blooming minus the number of flowers that have already stopped blooming.
提示 2
We can obtain these values efficiently using binary search.
提示 3
We can store the starting times in sorted order, which then allows us to binary search to find how many flowers have started blooming for a given time t.
提示 4
We do the same for the ending times to find how many flowers have stopped blooming at time t.
解法1:差分数组 + 有序哈希表 + 二分查找
关于类似题型的详解:LeetCode 1943. 描述绘画结果-CSDN博客
Java版:
class Solution {
public int[] fullBloomFlowers(int[][] flowers, int[] people) {
int n = people.length;
int[] ans = new int[n];
TreeMap<Integer, Integer> cnt = new TreeMap<>();
for (int[] flower : flowers) {
cnt.merge(flower[0], 1, Integer::sum);
cnt.merge(flower[1] + 1, -1, Integer::sum);
}
int m = cnt.size();
int[][] diff = new int[m][2];
int id = 0;
for (Map.Entry<Integer, Integer> entry: cnt.entrySet()) {
diff[id][0] = entry.getKey();
diff[id][1] = entry.getValue();
if (id > 0) {
diff[id][1] += diff[id - 1][1];
}
id++;
}
for (int i = 0; i < n; i++) {
int l = 0;
int r = m - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (diff[mid][0] <= people[i]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
if (r >= 0) {
ans[i] = diff[r][1];
} else {
ans[i] = 0;
}
}
return ans;
}
}
Pyhton3版:
from sortedcontainers import SortedDict
class Solution:
def fullBloomFlowers(self, flowers: List[List[int]], people: List[int]) -> List[int]:
cnt = SortedDict()
for l, r in flowers:
cnt[l] = cnt[l] + 1 if l in cnt else 1
cnt[r + 1] = cnt[r + 1] - 1 if r + 1 in cnt else -1
m = len(cnt)
diff = [[0] * 2 for _ in range(m)]
i = 0
for k, v in cnt.items():
diff[i] = [k, v]
if i > 0:
diff[i][1] += diff[i - 1][1]
i += 1
n = len(people)
ans = [0] * n
for i in range(n):
l = 0
r = m - 1
while l <= r:
mid = l + (r - l) // 2
if diff[mid][0] <= people[i]:
l = mid + 1
else:
r = mid - 1
if r >= 0:
ans[i] = diff[r][1]
else:
ans[i] = 0
return ans
复杂度分析
- 时间复杂度:O(m + nlogm),其中 n 为数组 people 的长度,m 为数组 flowers的长度,最坏情况下哈希表的长度也为m。维护变化量有序哈希表的时间复杂度为 O(m),将有序哈希表转化为数组并遍历数组求前缀和的时间复杂度为 O(m),生成返回数组的时间复杂度为 O(nlogm)。总的时间复杂度 O(m + m + nlogm) = O(m + nlogm)
- 空间复杂度:O(n + m),即为存储变化量的哈希表和数组的空间开销。
解法2:差分数组 + 哈希表 + 数组排序 + 二分查找
Java版:
class Solution {
public int[] fullBloomFlowers(int[][] flowers, int[] people) {
Map<Integer, Integer> cnt = new HashMap<>();
for (int[] flower : flowers) {
cnt.merge(flower[0], 1, Integer::sum);
cnt.merge(flower[1] + 1, -1, Integer::sum);
}
int m = cnt.size();
int[][] diff = new int[m][2];
int id = 0;
for (Map.Entry<Integer, Integer> entry : cnt.entrySet()) {
diff[id][0] = entry.getKey();
diff[id][1] = entry.getValue();
id++;
}
Arrays.sort(diff, new Comparator<int[]>() {
public int compare(int[] diff1, int[] diff2) {
return diff1[0] - diff2[0];
}
});
for (int i = 1; i < m; i++) {
diff[i][1] += diff[i - 1][1];
}
int n = people.length;
int[] ans = new int[n];
for (int i = 0; i < n; i++) {
int l = 0;
int r = m - 1;
while (l <= r) {
int mid = l + (r - l) / 2;
if (diff[mid][0] <= people[i]) {
l = mid + 1;
} else {
r = mid - 1;
}
}
ans[i] = r >= 0 ? diff[r][1] : 0;
}
return ans;
}
}
Python3版:
class Solution:
def fullBloomFlowers(self, flowers: List[List[int]], people: List[int]) -> List[int]:
cnt = defaultdict(lambda: 0)
for l, r in flowers:
cnt[l] += 1
cnt[r + 1] -= 1
m = len(cnt)
diff = sorted([[k, v] for k, v in cnt.items()])
for i in range(1, m):
diff[i][1] += diff[i - 1][1]
ans = []
for p in people:
l = 0
r = m - 1
while l <= r:
mid = l + (r - l) // 2
if diff[mid][0] <= p:
l = mid + 1
else:
r = mid - 1
if r >= 0:
ans.append(diff[r][1])
else:
ans.append(0)
return ans
复杂度分析
- 时间复杂度:O((m + n) logm),其中 n 为数组 people 的长度,m 为 数组 flowers 的长度。维护变化量哈希表的时间复杂度为 O(m),将哈希表转化为数组并排序的时间复杂度为 O(mlogm),遍历数组求前缀和的时间复杂度为 O(m),生成返回数组的时间复杂度为 O(nlogm)。总的时间复杂度 O(m + m + mlogm + m + nlogm) = O((m + n) logm)
- 空间复杂度:O(n + m),即为存储变化量的哈希表和数组的空间开销。