#P2270. 第1题-最后超时的定时任务索引号
-
1000ms
Tried: 738
Accepted: 152
Difficulty: 3
所属公司 :
华为
时间 :2024年10月16日-留学生
-
算法标签>模拟
第1题-最后超时的定时任务索引号
题目大意
该题目要求模拟一个具有固定容量的定时器系统,根据任务的超时时刻和添加顺序,决定最终保留哪些任务,并输出最后超时任务的索引
思路
创造一个优先队列,然后枚举每一个超时任务:
1.队列的大小<n,直接进队
2.队列的大小>=n,如果新任务的超时时间小于或等于队首的超时时间,则将队首任务移除,并将新任务插入队列。 如果新任务的超时时间大于队首的超时时间,则丢弃新任务。
代码如下
cpp
#include <bits/stdc++.h>
using namespace std;
// 定义一个足够大的数组来存储任务的超时时刻
const int MAX_TASKS = 1000005;
int timeoutTimes[MAX_TASKS];
int main(){
int capacity, taskCount; // capacity表示定时器系统的容量,taskCount表示任务数量
// 输入定时器系统容量
cin >> capacity;
// 输入任务数量
cin >> taskCount;
// 依次输入每个任务的超时时刻
for(int i = 0; i < taskCount; i++){
cin >> timeoutTimes[i];
}
// 定义一个优先队列(最大堆),存储任务的超时时刻和索引
// 优先队列中存储的是 pair<超时时刻, 任务索引>
priority_queue<pair<int, int>> timerQueue;
// 遍历所有任务,按照规则将任务添加到定时器系统中
for(int i = 0; i < taskCount; i++){
if(timerQueue.size() < capacity){
// 当定时器系统未满时,直接添加任务
timerQueue.push({timeoutTimes[i], i});
}
else{
// 定时器系统已满,比较新任务的超时时刻与当前系统中最晚的任务
if(timerQueue.top().first >= timeoutTimes[i]){
// 如果新任务的超时时刻较早或相等,则替换掉当前系统中最晚的任务
timerQueue.pop();
timerQueue.push({timeoutTimes[i], i});
}
// 否则,丢弃新任务
}
}
// 由于优先队列是最大堆,队顶元素是超时时刻最大的任务
// 若有多个任务超时刻相同,优先保留加入系统较晚的任务(即索引较大的任务)
pair<int, int> lastTimeoutTask = timerQueue.top();
// 输出最后超时的任务的索引号
cout << lastTimeoutTask.second << '\n';
return 0;
}
python
import heapq
def find_last_timeout_task(n, m, tasks):
# 使用一个堆来维护当前系统中的任务
# 堆中存储的是 (-t_i, -index_i),模拟最大堆
heap = []
for index, t_i in enumerate(tasks):
if len(heap) < n:
heapq.heappush(heap, (-t_i, -index))
else:
# 获取当前堆顶的任务
current_max_t, current_max_index = heap[0]
current_max_t = -current_max_t
current_max_index = -current_max_index
if t_i > current_max_t:
# 新任务的超时时间更大,丢弃新任务
continue
else:
# 替换堆顶任务为新任务
heapq.heappop(heap)
heapq.heappush(heap, (-t_i, -index))
# 遍历堆中的任务,找到超时时间最大的任务
# 如果有多个任务超时时间相同,选择索引最大的任务
max_t = -1
max_index = -1
for task in heap:
t_i = -task[0]
index = -task[1]
if t_i > max_t or (t_i == max_t and index > max_index):
max_t = t_i
max_index = index
return max_index
# 读取输入
if __name__ == "__main__":
import sys
import sys
# 读取定时器系统容量 n
n_line = sys.stdin.readline()
while n_line.strip() == '':
n_line = sys.stdin.readline()
n = int(n_line.strip())
# 读取定时任务数 m
m_line = sys.stdin.readline()
while m_line.strip() == '':
m_line = sys.stdin.readline()
m = int(m_line.strip())
# 读取定时任务列表
tasks_line = sys.stdin.readline()
while tasks_line.strip() == '':
tasks_line = sys.stdin.readline()
tasks = list(map(int, tasks_line.strip().split()))
# 调用函数并输出结果
result = find_last_timeout_task(n, m, tasks)
print(result)
java
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.Comparator;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取定时器系统容量 n
int capacity = sc.nextInt();
// 读取任务数量 m
int taskCount = sc.nextInt();
// 读取 m 个任务的超时时刻
int[] timeoutTimes = new int[taskCount];
for (int i = 0; i < taskCount; i++) {
timeoutTimes[i] = sc.nextInt();
}
// 定义一个优先队列(最大堆),存储任务的超时时刻和索引
PriorityQueue<Task> timerQueue = new PriorityQueue<>(new Comparator<Task>() {
@Override
public int compare(Task a, Task b) {
if (a.timeout != b.timeout) {
return b.timeout - a.timeout; // 按超时时刻从大到小排序
}
return b.index - a.index; // 如果超时时刻相同,按索引从大到小排序
}
});
// 遍历所有任务,按照规则将任务添加到定时器系统中
for (int i = 0; i < taskCount; i++) {
int timeout = timeoutTimes[i];
if (timerQueue.size() < capacity) {
// 当定时器系统未满时,直接添加任务
timerQueue.offer(new Task(timeout, i));
} else {
// 定时器系统已满,比较当前任务的超时时刻与队首任务
Task currentMaxTask = timerQueue.peek();
if (currentMaxTask.timeout >= timeout) {
// 如果当前任务的超时时刻较小或相等,替换掉队首任务
timerQueue.poll();
timerQueue.offer(new Task(timeout, i));
}
}
}
// 队首元素即为系统中超时时间最大的任务
Task lastTimeoutTask = timerQueue.peek();
// 输出最后超时任务的索引号
System.out.println(lastTimeoutTask.index);
sc.close();
}
}
// 定义一个任务类,包含超时时刻和索引
class Task {
int timeout;
int index;
Task(int timeout, int index) {
this.timeout = timeout;
this.index = index;
}
}
题目内容
有这样一个定时器系统:
(1)该系统精度为1刻度、可容纳n个超时任务(即容量为n);
(2)每个任务里包含该任务超时时刻t(当系统时钟到达t时,该任务开始执行),t为正整数;
(3)同一时刻超时的任务按照加入系统的先后顺序依次执行超时任务;
(4)当定时器系统中任务数不足n个时,可直接添加定时任务;
(5)当定时器系统中任务数达到n个时,假定待添加任务的超时时刻为ti,系统中最后执行的任务的超时时刻为tj;
如果ti>tj,丢弃待添加的任务;否则丢弃系统中最晚执行的超时任务,并将待添加任务加入系统中。
现给定该定时器系统容量n,短时内(不到1刻度)依次向该定时器系统添加m个定时任务tasks,假定当前时钟为0时刻,即向该定时器系统添加的任务都是尚未超时的任务。
请输出该定时器系统中最后超时的任务索引号,其中索引号是指:当前task在tasks中的下标(下标从0开始计);如果多个任务同时超时,请输出最大的索引号。
输入描述
第一行:定时器系统容量n;1<=n<=103
第二行:定时任务数m;1<=m<=106
第三行:定时任务列表内容tasks,每个数据通过空格隔开;1<=tasks[i]<=105。
输出描述
输出最后超时的任务索引号
样例1
输入
2
12
1 2 3 4 6 19 20 21 22 23 25 1
输出
11
说明
定时器系统容量为2,最多容纳2个定时任务,因此最终定时器里只会存在两个任务:
分别是1(索引号0)、1(索引号11),这两个任务同时超时,题目要求返回更大的索引,因此返回11
样例2
输入
1
2
10 2
输出
1
说明
定时器系统容量为1,最多容纳1个定时任务,因此最终定时器里只会存在1个任务:
2:
2对应索引号为1,因此返回1
样例3
输入
20
5
1 2 3 4 5
输出
4
说明
定时器系统容量为20,最多容纳20个定时任务,而添加的任务数为5,没有超过定时器系统规格,因此最终定时器里会存在以下任务:1 2 3 4 5;
5最晚超时,因此返回5对应的下标4