期末考试 | Google Kickstart 2021 D 轮
是时候进行算法和数据结构的期末考试了!
Edsger 准备了N组问题。每组由难度递增的问题组成;第 i 个集合可以用两个整数 Ai 和 Bi (Ai≤Bi) 来描述,表示这个集合包含困难 Ai, Ai+1…, Bi。在所有集合的所有问题中,保证没有两个问题具有相同的难度。
本学期 Edsger 必须测试M个学生。他想用他的一组中的一个问题来测试每个学生。没有两个学生可以得到完全相同的问题,所以当 Edsger 测试一个有问题的学生时,他不能再使用这个问题了。通过无数的讲座、练习和项目,Edsger 已经衡量了学生 j 的技能水平 Sj,并希望给那个学生一个难度 Sj 的问题。不幸的是,这并不总是可能的,因为 Edsger 可能没有准备好这个难度的问题,或者他可能已经提前向其他学生提出了这个问题。因此,Edsger 将为第 j 个学生选择一个难度为 Pj 的问题,其方式为 |Pj−Sj|是最小的,并且在第 j 个学生之前没有给任何学生一个难度 Pj 的问题。在平局的情况下,Edsger 将始终选择更容易的问题。请注意,为第 j 个学生选择的问题可能会影响为以后测试的所有学生选择的问题,因此您必须按照学生在输入中出现的顺序来处理他们。
由于跟踪所有问题可能相当复杂,您能否帮助 Edsger 并确定他应该为所有学生提供哪些问题?
或者
给定一个包含N对的数组questionRange ,其起始值和结束值作为难度级别的范围,一个大小为M的数组arr表示每个学生可以尝试的难度级别。任务是 将issueRange中的唯一整数X分配给数组arr中的每个整数,使得| arr[i] - X |被最小化。如果两个最接近arr[i]的值相等,则必须选择一个较小的难度值。 X值必须按学生的顺序分配给学生,因为不能将相同的X值分配给多个学生。打印分配给每个学生的X值。
例子:
Input: N = 5, M = 4, arr = [14, 24, 24, 4], problemRange = [[1, 2], [6, 7], [9, 12], [24, 24], [41, 50]]
Output: 12 24 11 2
Explanation: values which can be assigned to the students are {1, 2}, {6, 7}, {9, 10, 11, 12}, {24}, {41, 42, 43, 44, 45, 46, 47, 48, 49, 50} 12 is assigned to first student who can attempt questions of difficulty level 14 as it is the closest to 14. 24 is closest to 24. Next student can also attempt question of 24 difficulty but 24 from the range is already chosen and the next closest is 11. 2 and 6 is closest to last student of difficulty 4, since 2 and 6 both are similarly close to 4, easier questions of difficulty level 2 is assigned.
Input: N = 1, M = 1, arr = [24], problemRange = [[42, 42]]
Output: 42
方法:给定问题可以通过以下步骤解决:
- 使用映射将范围的开始存储为键,将范围的结束存储为值
- 迭代数组并为其中的每个元素在地图中找到它的lower_bound
- 可能有两种情况: Lower_bound将返回指向等于arr[i]的键或刚好大于arr[i]的键的迭代器
- 假设由lower_bound提供的迭代器 be it和pre是它之前的迭代器(当it = mp.begin()时pre将等于它)
- pre.first<=arr[i]<=pre.second或it.first<=arr[i]<=it.second都是真的。 arr[i]将位于此范围的前向部分或后向部分
- 每次将值分配给arr[i]之前的范围都会从地图中删除,并添加一个新范围,如图所示
- 添加两个新范围或添加一个新范围,如下图所示:
下面是上述方法的实现:
C++
// C++ implementation for the above approach
#include
using namespace std;
void solve(long long int N, long long int M,
vector >
problemRange,
vector arr)
{
// Store the problem range in a map
map mp;
for (long long int i = 0; i < N; i++) {
long long int a, b;
a = problemRange[i].first;
b = problemRange[i].second;
mp[a] = b;
}
vector ans(M);
for (long long int i = 0; i < M; i++) {
auto it = mp.lower_bound(arr[i]);
auto pre = it;
if (it != mp.begin())
pre--;
// If answer lies in a valid range
if (pre->first <= arr[i]
&& arr[i] <= pre->second) {
ans[i] = arr[i];
long long int st = pre->first,
end = pre->second;
mp.erase(pre);
long long int left = arr[i] - 1,
right = arr[i] + 1;
if (st <= left) {
mp[st] = left;
}
if (end >= right) {
mp[right] = end;
}
}
// If answer is not in a valid range
else {
long long int op1 = pre->second,
op2 = it->first;
if (abs(arr[i] - op1) <= abs(arr[i] - op2)) {
ans[i] = op1;
long long int st = pre->first,
end = op1 - 1;
mp.erase(pre);
if (st <= end)
mp[st] = end;
}
else {
ans[i] = op2;
long long int st = it->first + 1,
end = it->second;
mp.erase(it);
if (st <= end)
mp[st] = end;
}
}
}
for (auto it : ans)
cout << it << " ";
cout << endl;
}
// Driver code
int main()
{
long long int N, M;
N = 5;
M = 4;
// Student difficulty level
vector arr = { 14, 24, 24, 4 };
vector >
problemRange = { { 1, 2 },
{ 6, 7 },
{ 9, 12 },
{ 24, 24 },
{ 41, 50 } };
solve(N, M, problemRange, arr);
return 0;
}
12 24 11 2
时间复杂度: MLog(N)
辅助空间: O(N)