青训营X豆包MarsCode 技术训练营 字节青训营笔记2| 豆包MarsCode AI刷题

69 阅读5分钟

小M的多任务下载器挑战

题目背景

小M的程序设计大作业是编写一个多任务下载器,在做到计算任务 并发数 的时候遇到了困难

题目内容

在一次下载中,总共包含N个任务,每个任务会在第x秒开始、并持续y秒。 小M想要知道,在一次下载中,同时最多会有多少个任务正在下载。

数据输入

第一行输入一个正整数N,代表总共有N个任务。 之后共N行,每行包含两个正整数xyx代表任务的开始时间,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号任务正在进行。

问题分析

  1. 任务开始时间 x 和持续时间 y,任务的结束时间是 x + y
  2. 每个任务用两个事件来表示:任务开始的时间 x,任务结束的时间 x + y
  3. 要统计每一秒钟有多少个任务正在进行。可以将所有任务的开始和结束时间抽象成时间事件,事件的类型用 1 表示开始,-1 表示结束。
  4. 对这些事件进行排序,最后通过扫描这些事件来计算最大并发数。

解答过程

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 表达式接收两个参数 ab

排序规则

若时间相同,结束事件优先处理 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实现、解决队头阻塞、加密减少握手次数、支持快速启动