华为OD机试真题 新系统 2026-04-29 Java&Go&C语言 实现【日志文件异常检测】
目录
题目
在某系统的日志监控服务中,需要实时检测日志文件中的异常模式。系统每天会产生大量日志记录,每条日志记录包含一个字符串 标识。异常模式定义为:在同一时间段内,至少出现 3 次的日志标识。
请编写一个程序,找出所有出现次数大于等于 3 次的日志标识,并按照以下规则输出:
首先按照出现次数从高到低排序
如果出现次数相同,则按照首次出现的先后顺序排序
输入描述
输入所有日志标识以空格分割。日志标识由大小写字母、数字和下划线组成,长度不超过 50。日志数量范围为[1,10000]
输出描述
输出所有出现次数大于等于 3 次的日志标识,按照上述排序规则输出.以空格分割。如果没有符合条件的日志标识,则输出 “NONE”
用例1
输入
error_404 error_404 warning_500 error_404 info_200 warning_500 warning_500 info_200
输出
error_404 warning_500
说明
error_404出现了 3次(数组第0、1、3个元素),首次出现位置是第0个元素
warning_500 出现了 3 次(数组第2、5、6个元素),首次出现位置是第2个元素
info_200 只出现了 2 次(数组第4、7个元素),不符合条件
error_404 和 warning_500 出现次数相同(都是3次),按照首次出现的先后顺序,先输出 error_404,再输出 warning_500, 注意:虽然 info_200 出现了 2 次,但题目要求的是出现次数大于等于 3 次,因此不输出 info_200用例2
输入
test_case test_case test_case2 test_case2 test_case2输出
test_case2说明
test_case 出现了 2 次,不符合条件test_case2 出现了 3 次,首次出现位置是数组第3个元素
思路
比较简单的排序算法题目,用一次遍历统计两个信息:
- 每个日志标识出现了多少次
- 每个日志标识第一次出现的位置
然后把所有出现次数大于等于 3 的标识筛出来,按下面规则排序:
- 第一关键字:出现次数降序
- 第二关键字:首次出现位置升序
最后:
- 如果筛选结果为空,输出 NONE
- 否则按排序后的顺序输出日志标识,单行空格分隔
Code
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringBuilder sb = new StringBuilder();
String line;
// 读取全部输入,兼容多空格和多行情况。
while ((line = br.readLine()) != null) {
sb.append(line).append(" ");
}
String input = sb.toString().trim();
if (input.isEmpty()) {
System.out.print("NONE");
return;
}
String[] logs = input.split("\\s+");
// 统计出现次数。
Map<String, Integer> countMap = new HashMap<>();
// 记录首次出现位置。
Map<String, Integer> firstIndex = new HashMap<>();
for (int i = 0; i < logs.length; i++) {
String log = logs[i];
countMap.put(log, countMap.getOrDefault(log, 0) + 1);
firstIndex.putIfAbsent(log, i);
}
List<String[]> candidates = new ArrayList<>();
for (String log : countMap.keySet()) {
int cnt = countMap.get(log);
if (cnt >= 3) {
candidates.add(new String[]{
log,
String.valueOf(cnt),
String.valueOf(firstIndex.get(log))
});
}
}
if (candidates.isEmpty()) {
System.out.print("NONE");
return;
}
// 先按次数降序,再按首次出现位置升序。
candidates.sort((a, b) -> {
int cntA = Integer.parseInt(a[1]);
int cntB = Integer.parseInt(b[1]);
if (cntA != cntB) {
return Integer.compare(cntB, cntA);
}
int idxA = Integer.parseInt(a[2]);
int idxB = Integer.parseInt(b[2]);
return Integer.compare(idxA, idxB);
});
StringBuilder out = new StringBuilder();
for (int i = 0; i < candidates.size(); i++) {
if (i > 0) out.append(" ");
out.append(candidates.get(i)[0]);
}
System.out.print(out);
}
}
C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXN 10005
#define MAXLEN 55
#define MAXTOKENS 10005
typedef struct {
char log[MAXLEN];
int count;
int firstIndex;
} Node;
int cmp(const void *a, const void *b) {
Node *x = (Node *)a;
Node *y = (Node *)b;
// 次数高的排前面。
if (x->count != y->count) return y->count - x->count;
// 次数相同则首次出现早的排前面。
return x->firstIndex - y->firstIndex;
}
int main() {
char logs[MAXTOKENS][MAXLEN];
int logCount = 0;
// scanf("%s") 会自动按空白字符切分,适合这道题。
while (scanf("%54s", logs[logCount]) == 1) {
logCount++;
}
if (logCount == 0) {
printf("NONE");
return 0;
}
Node nodes[MAXTOKENS];
int nodeCount = 0;
// 用顺序表统计每个标识的次数和首次位置。
for (int i = 0; i < logCount; i++) {
int found = -1;
for (int j = 0; j < nodeCount; j++) {
if (strcmp(nodes[j].log, logs[i]) == 0) {
found = j;
break;
}
}
if (found == -1) {
strcpy(nodes[nodeCount].log, logs[i]);
nodes[nodeCount].count = 1;
nodes[nodeCount].firstIndex = i;
nodeCount++;
} else {
nodes[found].count++;
}
}
Node candidates[MAXTOKENS];
int candidateCount = 0;
for (int i = 0; i < nodeCount; i++) {
if (nodes[i].count >= 3) {
candidates[candidateCount++] = nodes[i];
}
}
if (candidateCount == 0) {
printf("NONE");
return 0;
}
qsort(candidates, candidateCount, sizeof(Node), cmp);
for (int i = 0; i < candidateCount; i++) {
if (i > 0) printf(" ");
printf("%s", candidates[i].log);
}
return 0;
}
Go
package main
import (
"bufio"
"fmt"
"os"
"sort"
)
type Node struct {
log string
count int
firstIndex int
}
func main() {
in := bufio.NewReader(os.Stdin)
logs := make([]string, 0)
for {
var s string
_, err := fmt.Fscan(in, &s)
if err != nil {
break
}
logs = append(logs, s)
}
if len(logs) == 0 {
fmt.Print("NONE")
return
}
countMap := make(map[string]int)
firstIndex := make(map[string]int)
for i, log := range logs {
countMap[log]++
if _, exists := firstIndex[log]; !exists {
firstIndex[log] = i
}
}
candidates := make([]Node, 0)
for log, cnt := range countMap {
if cnt >= 3 {
candidates = append(candidates, Node{
log: log,
count: cnt,
firstIndex: firstIndex[log],
})
}
}
if len(candidates) == 0 {
fmt.Print("NONE")
return
}
sort.Slice(candidates, func(i, j int) bool {
if candidates[i].count != candidates[j].count {
return candidates[i].count > candidates[j].count
}
return candidates[i].firstIndex < candidates[j].firstIndex
})
for i, node := range candidates {
if i > 0 {
fmt.Print(" ")
}
fmt.Print(node.log)
}
}
【华为od机试真题Python+JS+Java+Go合集】【超值优惠】:Py/JS/Java/Go合集
【华为od机试真题Python】:Python真题题库
【华为od机试真题JavaScript】:JavaScript真题题库
【华为od机试真题Java&Go】:Java&Go真题题库
【华为od机试真题C++】:C++真题题库
【华为od机试真题C语言】:C语言真题题库
【华为od面试手撕代码题库】:面试手撕代码题库
【华为od机试面试交流群】【文章底部有二维码链接,可扫码加交流群】
华为OD机试:二本院校有机会吗?
有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。
更多推荐




所有评论(0)