HTTP 访问日志峰值请求数(JAVA /Py/C/C++/Js/Go)题解
华为OD机试真题 新系统 华为OD上机考试真题新系统 11月8号 100分题型
华为OD机试新系统真题目录点击查看: 华为OD机试新系统真题题库目录|机考题库 + 算法考点详解
题目描述
网关为每个到达的 HTTP 请求记录一行访问日志(含方法、路径、时间戳)。给定按到达顺序排列的日志与窗口大小 windowMs,以每条请求的时间戳作为窗口左端点 t,求半开窗口 [t, t+windowMs) 内最多包含多少条请求。
输入
输入为一个字符串,格式为 "windowMs METHOD PATH TIMESTAMP METHOD PATH TIMESTAMP ...":首字段为 windowMs,其后每三个字段为一条请求(METHOD、PATH、TIMESTAMP),字段之间以单个空格分隔。
输出
返回一个整数值:所有以请求时间戳为左端点的窗口中,包含请求数的最大值;windowMs = 0 或无请求时返回 0。
数据范围:
0 <= windowMs <= 10^90 <= TIMESTAMP <= 10^9,且按到达顺序非递减(允许同一毫秒有多条请求)METHOD、PATH均不含空格
样例1
输入
1000 GET /api/users 1000 GET /api/users 1200 POST /login 1500 GET /api/users 1800 GET /api/users 2050
输出
4
说明
时间戳为 [1000, 1200, 1500, 1800, 2050],以左端 1000 的窗口 [1000, 2000) 包含 4 条请求。
样例2
输入
1000 GET /api/users 1000 POST /login 1000 GET /api/orders 1000 GET /api/users 2000 GET /api/users 2500
输出
3
说明
前 3 条请求的时间戳都是 1000,窗口 [1000, 2000) 包含 3 条请求(2000 落在右端点,半开区间不包含)。
样例3
输入
0 GET /api/users 1000 GET /api/users 2000
输出
0
说明
windowMs = 0,半开窗口为空,返回 0。
题解
思路:滑动窗口
- 预处理输入字符串,提取出
windowMs和所有请求时间戳使用数组timestamps(题目保证升序) - 如果
windowMs小于等于0,直接返回0. - 使用滑动窗口进行求解,初始定义
left = 0,,从前往后移动右窗口,当前窗口为right时,处理逻辑如下- 保证
left, right满足timestamps[left] + windowMs > timestamps[right], 通过不断移动左边界。 - 那么当前
left作为右端点能获得的最大长度为curLen = right - left + 1 - 将
ans与curLen进行对比,尝试更新最大值。
- 保证
- 按照3逻辑处理之后,对应ans就是结果。
C++
cpp
#include <bits/stdc++.h>
#include <vector>
using namespace std;
using ll = long long;
// 通用 切割函数 函数 将字符串str根据delimiter进行切割
vector<string> split(const string& str, const string& delimiter) {
vector<string> result;
size_t start = 0;
size_t end = str.find(delimiter);
while (end != string::npos) {
result.push_back(str.substr(start, end - start));
start = end + delimiter.length();
end = str.find(delimiter, start);
}
// 添加最后一个部分
result.push_back(str.substr(start));
return result;
}
int solve(string s) {
vector<string> part = split(s, " ");
int windowMs = stoi(part[0]);
int n = part.size();
if (windowMs <= 0) {
return 0;
}
// 收集所有请求时间戳
vector<int> timestamps;
for (int i = 3; i < n; i += 3) {
int time = stoi(part[i]);
timestamps.push_back(time);
}
int ans = 0;
int left = 0;
for (int right = 0; right < timestamps.size(); right++) {
while (left < right && timestamps[left] + windowMs <= timestamps[right]) {
left++;
}
int curLen = right - left + 1;
ans = max(ans, curLen);
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string s;
getline(cin, s);
int ans = solve(s);
cout << ans << '\n';
return 0;
}
Java
java
import java.util.*;
public class Main {
static int solve(String s) {
String[] part = s.trim().split("\\s+");
int windowMs = Integer.parseInt(part[0]);
int n = part.length;
if (windowMs <= 0) {
return 0;
}
// 收集所有请求时间戳
List<Integer> timestamps = new ArrayList<>();
for (int i = 3; i < n; i += 3) {
int time = Integer.parseInt(part[i]);
timestamps.add(time);
}
int ans = 0;
int left = 0;
for (int right = 0; right < timestamps.size(); right++) {
while (left < right &&
timestamps.get(left) + windowMs <= timestamps.get(right)) {
left++;
}
int curLen = right - left + 1;
ans = Math.max(ans, curLen);
}
return ans;
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
System.out.println(solve(s));
sc.close();
}
}
Python
python
def solve(s):
part = s.split()
windowMs = int(part[0])
n = len(part)
if windowMs <= 0:
return 0
# 收集所有请求时间戳
timestamps = []
for i in range(3, n, 3):
time = int(part[i])
timestamps.append(time)
ans = 0
left = 0
for right in range(len(timestamps)):
while left < right and timestamps[left] + windowMs <= timestamps[right]:
left += 1
curLen = right - left + 1
ans = max(ans, curLen)
return ans
if __name__ == "__main__":
s = input()
print(solve(s))
JavaScript
js
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function solve(s) {
const part = s.trim().split(/\s+/);
const windowMs = parseInt(part[0]);
const n = part.length;
if (windowMs <= 0) {
return 0;
}
// 收集所有请求时间戳
const timestamps = [];
for (let i = 3; i < n; i += 3) {
const time = parseInt(part[i]);
timestamps.push(time);
}
let ans = 0;
let left = 0;
for (let right = 0; right < timestamps.length; right++) {
while (left < right &&
timestamps[left] + windowMs <= timestamps[right]) {
left++;
}
const curLen = right - left + 1;
ans = Math.max(ans, curLen);
}
return ans;
}
rl.on('line', (s) => {
console.log(solve(s));
rl.close();
});
Go
go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func solve(s string) int {
part := strings.Fields(s)
windowMs, _ := strconv.Atoi(part[0])
n := len(part)
if windowMs <= 0 {
return 0
}
// 收集所有请求时间戳
timestamps := make([]int, 0)
for i := 3; i < n; i += 3 {
time, _ := strconv.Atoi(part[i])
timestamps = append(timestamps, time)
}
ans := 0
left := 0
for right := 0; right < len(timestamps); right++ {
for left < right &&
timestamps[left]+windowMs <= timestamps[right] {
left++
}
curLen := right - left + 1
if curLen > ans {
ans = curLen
}
}
return ans
}
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
s := scanner.Text()
fmt.Println(solve(s))
}
C语言
cpp
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int solve(char *s) {
char *part[100000];
int n = 0;
// 切割字符串,保留每个字段的原始内容
char *token = strtok(s, " \t\r\n");
while (token != NULL) {
part[n++] = token;
token = strtok(NULL, " \t\r\n");
}
int windowMs = atoi(part[0]);
if (windowMs <= 0) {
return 0;
}
// 收集所有请求时间戳
int timestamps[100000];
int m = 0;
for (int i = 3; i < n; i += 3) {
int time = atoi(part[i]);
timestamps[m++] = time;
}
int ans = 0;
int left = 0;
for (int right = 0; right < m; right++) {
while (left < right &&
timestamps[left] + windowMs <= timestamps[right]) {
left++;
}
int curLen = right - left + 1;
if (curLen > ans) {
ans = curLen;
}
}
return ans;
}
int main() {
char s[10000000];
fgets(s, sizeof(s), stdin);
printf("%d\n", solve(s));
return 0;
}