小M的多任务下载器挑战
题目背景
小M的程序设计大作业是编写一个多任务下载器,在做到计算任务 并发数 的时候遇到了困难。
题目内容
在一次下载中,总共包含N个任务,每个任务会在第x秒开始、并持续y秒。 小M想要知道,在一次下载中,同时最多会有多少个任务正在下载。
数据输入
第一行输入一个正整数N,代表总共有N个任务。 之后共N行,每行包含两个正整数x、y,x代表任务的开始时间,y代表任务的持续时间。
数据输出
输出包含一个整数,代表最高的任务并发数。
数据与约定
对于30%的数据,1≤N≤1,0001≤N≤1,000,1≤x,y≤1,0001≤x,y≤1,000。 对于50%的数据,1≤N≤1,000,0001≤N≤1,000,000,1≤x,y≤1,000,0001≤x,y≤1,000,000。 对于100%的数据,1≤N≤1,000,0001≤N≤1,000,000,1≤x,y≤1,000,000,0001≤x,y≤1,000,000,000。
示例1
输入
2
1 2
2 3
输出 2
说明 第一个任务在第一秒开始,持续两秒;第二个任务在第二秒开始,持续三秒。故在第二秒时有两个任务同时在进行,最大并发数为2。
示例2
输入
4
1 2
2 3
3 5
4 3
输出 3
说明 4个任务的时间区间分别为[1,2], [2,4], [3,7], [4,6]。 故在第4秒的时候,第2、3、4号任务正在进行。
问题分析
- 任务开始时间
x和持续时间y,任务的结束时间是x + y。 - 每个任务用两个事件来表示:任务开始的时间
x,任务结束的时间x + y。 - 要统计每一秒钟有多少个任务正在进行。可以将所有任务的开始和结束时间抽象成时间事件,事件的类型用
1表示开始,-1表示结束。 - 对这些事件进行排序,最后通过扫描这些事件来计算最大并发数。
解答过程
1.利用键值对,创建事件列表
pair.first是时间,pair.second是事件类型(1表示开始,-1表示结束) std::vector<std::pair<int, int>> events; 2.task[0]代表开始时间, task[1]代表持续时间。 int end = task[0] + task[1]; 结束时间=开始时间+持续时间
把开始事件和结束事件放入事件数组 events.push_back({start, 1}); //开始事件 events.push_back({end, -1}); //结束事件 3.events数组键值对排序 按照时间排序,若时间相同,结束事件优先处理 sort(events.begin(), events.end(), [](const std::pair<int, int>& a, const std::pair<int, int>& b)
events.begin() 起始迭代器 和 events.end()结束迭代器
[](const std::pair<int, int>& a, const std::pair<int, int>& b) 是一个 lambda 表达式,它指定了排序过程中用来比较元素的规则, lambda 表达式接收两个参数 a 和 b。
排序规则
若时间相同,结束事件优先处理 if (a.first == b.first) { return a.second < b.second; }
按照时间排序 return a.first < b.first; 4.通过扫描事件计算最大并发数 currentCount当前并发数,maxCount最大并发数。 for (const auto& event : events) { currentCount += event.second; maxCount = std::max(maxCount, currentCount); }
主要采用了键值对和排序算法,对数组进行排序后,通过扫描事件计算最大并发数。
代码如下
#include <iostream>
#include <vector>
#include <algorithm>
int solution(int n, std::vector<std::vector<int>> array) {
std::vector<std::pair<int, int>> events;
for (const auto& task : array) {
int start = task[0];
int end = task[0] + task[1];
events.push_back({start, 1});
events.push_back({end, -1});
}
std::sort(events.begin(), events.end(), []
(const std::pair<int, int>& a,
const std::pair<int, int>& b) {
if (a.first == b.first) {
return a.second < b.second;
}
return a.first < b.first;
});
int currentCount = 0;
int maxCount = 0;
for (const auto& event : events) {
currentCount += event.second;
maxCount = std::max(maxCount, currentCount);
}
return maxCount;
}
int main() {
std::cout << (solution(2, {{1, 2}, {2, 3}}) == 2) << std::endl;
std::cout << (solution(4, {{1, 2}, {2, 3}, {3, 5}, {4, 3}}) == 3) << std::endl;
return 0;
}
示例 1:
输入:
2
1 2
2 3
任务 1 从第 1 秒开始,持续 2 秒;任务 2 从第 2 秒开始,持续 3 秒。
- 事件 1: 任务 1 开始于第 1 秒。
- 事件 2: 任务 1 结束于第 3 秒。
- 事件 3: 任务 2 开始于第 2 秒。
- 事件 4: 任务 2 结束于第 5 秒。
排序后的事件为:
(1, 1), (2, 1), (3, -1), (5, -1)
遍历这些事件,最大并发数为 2。
示例 2:
输入:
4
1 2
2 3
3 5
4 3
排序后的事件为:
(1, 1), (2, 1), (3, 1), (3, -1), (4, 1), (5, -1), (6, -1), (7, -1)
最大并发数为 3。
HTTP协议
HTTP:超文本传输协议(Hypertext Transfer Protocol)
协议开始
协议元数据
Text
协议结束
POST /sis HTTP/1.1
who: Alex
Content-Type: text/plain
Host:127.0.0.1:8888
Content-Length:28
Let's watch a movie together
HTTP/1.1 200 0K
Server: hertz
Date: Thu,21 Apr 2022 11:46:32
GMTContent-Type: text/plain;charset=utf-8
Content-Length:2
Upstream-Caught:1650541592984580
0K
请求行/状态行
请求头/响应头
请求体/响应体
方法名,URL,协议版本
常见方法名
GET,HEAD,POST,PUT,DELETE,CONNECT,OPTIONS,TRACE,PATCH
协议版本,状态码,状态码描述
状态码:
1xx:信息类
2xx:成功
3xx:重定向
4xx:客户端错误5xX:服务端错误
package main
import(
"context"
"code.byted.org/middleware/hertz/pkg/app"
"code.byted.org/middleware/hertz/pkg/app/server"
func main( ){
h := server.New()
TTCctx.Data(200,"text/plain:charset=utf-8",[]byte("OK"))
h.Spin()
}
业务层
服务治理层
中间件层
路由层
协议编(解)码层
传输层
HTTP1:队头阻塞、传输效率低、明文传输不安全
HTTP2:多路复用、头部压缩、二进制协议
QUIC:基于UDP实现、解决队头阻塞、加密减少握手次数、支持快速启动