华为OD新系统机试真题 - 日志文件异常检测

日志文件异常检测(Py/Java/C/C++/Js/Go)

华为OD机试真题 华为OD上机考试真题 4月29号 100分题型

华为OD机试真题目录点击查看: 华为OD机试真题题库目录|机考题库 + 算法考点详解

题目描述

在某系统的日志监控服务中,需要实时检测日志文件中的异常模式。系统每天会产生大量日志记录,每条日志记录包含一个字符串标识。异常模式定义为:在同一时间段内,至少出现 3 次的日志标识。

请编写一个程序,找出所有出现次数大于等于 3 次的日志标识,并按照以下规则输出:

  1. 首先按照出现次数从高到低排序
  2. 如果出现次数相同,则按照首次出现的先后顺序排序

输入描述

输入所有日志标识以空格分割。

日志标识由大小写字母、数字和下划线组成,长度不超过 50。日志数量范围为[1,10000]

输出描述

输出所有出现次数大于等于 3 次的日志标识,每行一个,按照上述排序规则输出.以空格分割。

如果没有符合条件的日志标识,则输出 "NONE"

用例1

输入

none 复制代码
error_404 error_404 warning_500 error_404 info_200 warning_500 warning_500 info_200

输出

none 复制代码
error_404 warning_500

说明

  1. error_404出现了 3次(数组第0、1、3个元素),首次出现位置是第0个元素
  2. warning_500 出现了 3 次(数组第2、5、6个元素),首次出现位置是第2个元素
  3. info_200 只出现了 2 次(数组第4、7个元素),不符合条件
  4. error_404 和 warning_500 出现次数相同(都是3次),按照首次出现的先后顺序,先输出 error_404,再输出 warning_500, 注意:虽然 info_200 出现了 2 次,但题目要求的是出现次数大于等于 3 次,因此不输出 info_200

用例2

输入

none 复制代码
test_case test_case test_case2 test_case2 test_case2

输出

none 复制代码
test_case2

说明

test_case 出现了 2 次,不符合条件

test_case2 出现了 3 次,首次出现位置是数组第3个元素

题解

思路:数据结构运用 + 自定义排序

  1. 首先使用两个哈希表logcount, logFirstPos或者类似结构分别统计每个日志出现的次数和首次出现位置。
  2. 利用1中统计信息,筛选出次数大于等于3的日志放入结果数组中。
  3. 将结果数组中日志按照首先按照出现次数从高到低排序,如果出现次数相同,则按照首次出现的先后顺序排序规则进行自定义排序。
  4. 返回结果,根据题意进行输出即可。

c++

c++ 复制代码
#include<iostream>
#include<vector>
#include<string>
#include <utility> 
#include <sstream>
#include<algorithm> 
#include<cmath>
#include<map>
using namespace std;

// 通用 切割函数 函数 将字符串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;
}

vector<string> findAnomalyLogs(vector<string>& records) {
    // 出现次数
    map<string,int> logcount;
    // 首次出现位置
    map<string, int> logFirstPos;
    for (int i = 0 ; i < records.size(); i++) {
        string record = records[i];
        logcount[record]++;
        if (logFirstPos.find(record) == logFirstPos.end()) {
            logFirstPos[record] = i;
        }
    }

    // 筛选出出现次数大于等于3
    vector<string> ans;
    for (auto &p : logcount) {
        if (p.second >= 3) {
            ans.push_back(p.first);
        }
    }

    // 自定义排序,先按次数,次数相同按第一次出现位置
    sort(ans.begin(), ans.end(), [&](string&a , string& b) {
        if (logcount[a] != logcount[b]) {
            return logFirstPos[a] < logFirstPos[b];
        }
        return logcount[a] > logcount[b];
    });
    return ans;
}


int main() {
    string input;
    getline(cin, input);
    vector<string> records = split(input, " ");

    vector<string> ans = findAnomalyLogs(records);
    // 输出结果
    if (ans.empty()) {
        cout << "NONE";
        return 0;
    }
    for (int i = 0; i < ans.size(); i++) {
        cout << ans[i];
        if (i != ans.size() - 1) {
            cout << " ";
        }
    }
    return 0;
}

JAVA

JAVA 复制代码
import java.util.*;
import java.io.*;

// 主类
public class Main {

    // 查找异常日志
    public static List<String> findAnomalyLogs(List<String> records) {
        // 出现次数
        Map<String, Integer> logcount = new HashMap<>();
        // 首次出现位置
        Map<String, Integer> logFirstPos = new HashMap<>();

        for (int i = 0; i < records.size(); i++) {
            String record = records.get(i);
            logcount.put(record, logcount.getOrDefault(record, 0) + 1);
            if (!logFirstPos.containsKey(record)) {
                logFirstPos.put(record, i);
            }
        }

        // 筛选出出现次数大于等于3
        List<String> ans = new ArrayList<>();
        for (String key : logcount.keySet()) {
            if (logcount.get(key) >= 3) {
                ans.add(key);
            }
        }

        // 自定义排序:先按次数降序,次数相同按首次位置升序
        ans.sort((a, b) -> {
            if (!logcount.get(a).equals(logcount.get(b))) {
                return logcount.get(b) - logcount.get(a);
            }
            return logFirstPos.get(a) - logFirstPos.get(b);
        });

        return ans;
    }

    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        String input = br.readLine();

        List<String> records = Arrays.asList(input.split(" "));

        List<String> ans = findAnomalyLogs(records);

        // 输出结果
        if (ans.isEmpty()) {
            System.out.print("NONE");
            return;
        }

        for (int i = 0; i < ans.size(); i++) {
            System.out.print(ans.get(i));
            if (i != ans.size() - 1) {
                System.out.print(" ");
            }
        }
    }
}

Python

python 复制代码
import sys

# 查找异常日志
def findAnomalyLogs(records):
    # 出现次数
    logcount = {}
    # 首次出现位置
    logFirstPos = {}

    for i, record in enumerate(records):
        logcount[record] = logcount.get(record, 0) + 1
        if record not in logFirstPos:
            logFirstPos[record] = i

    # 筛选出出现次数大于等于3
    ans = [k for k, v in logcount.items() if v >= 3]

    # 自定义排序:先按次数降序,再按首次位置升序
    ans.sort(key=lambda x: (-logcount[x], logFirstPos[x]))

    return ans


# 读取输入
input_line = sys.stdin.readline().strip()
records = input_line.split()

ans = findAnomalyLogs(records)

# 输出结果
if not ans:
    print("NONE")
else:
    print(" ".join(ans))

JavaScript

js 复制代码
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 查找异常日志
function findAnomalyLogs(records) {
    // 出现次数
    const logcount = new Map();
    // 首次出现位置
    const logFirstPos = new Map();

    for (let i = 0; i < records.length; i++) {
        let record = records[i];
        logcount.set(record, (logcount.get(record) || 0) + 1);
        if (!logFirstPos.has(record)) {
            logFirstPos.set(record, i);
        }
    }

    // 筛选
    let ans = [];
    for (let [k, v] of logcount.entries()) {
        if (v >= 3) ans.push(k);
    }

    // 排序:先按次数降序,再按首次位置升序
    ans.sort((a, b) => {
        if (logcount.get(a) !== logcount.get(b)) {
            return logcount.get(b) - logcount.get(a);
        }
        return logFirstPos.get(a) - logFirstPos.get(b);
    });

    return ans;
}

rl.on('line', function(line) {
    let records = line.trim().split(" ");
    let ans = findAnomalyLogs(records);

    if (ans.length === 0) {
        console.log("NONE");
    } else {
        console.log(ans.join(" "));
    }
});

Go

go 复制代码
package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strings"
)

// 查找异常日志
func findAnomalyLogs(records []string) []string {
	// 出现次数
	logcount := make(map[string]int)
	// 首次出现位置
	logFirstPos := make(map[string]int)

	for i, record := range records {
		logcount[record]++
		if _, ok := logFirstPos[record]; !ok {
			logFirstPos[record] = i
		}
	}

	// 筛选
	ans := []string{}
	for k, v := range logcount {
		if v >= 3 {
			ans = append(ans, k)
		}
	}

	// 排序
	sort.Slice(ans, func(i, j int) bool {
		a, b := ans[i], ans[j]
		if logcount[a] != logcount[b] {
			return logcount[a] > logcount[b] // 次数降序
		}
		return logFirstPos[a] < logFirstPos[b] // 位置升序
	})

	return ans
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	input, _ := reader.ReadString('\n')
	input = strings.TrimSpace(input)

	records := strings.Split(input, " ")

	ans := findAnomalyLogs(records)

	// 输出
	if len(ans) == 0 {
		fmt.Print("NONE")
		return
	}

	for i, v := range ans {
		if i > 0 {
			fmt.Print(" ")
		}
		fmt.Print(v)
	}
}

C语言

cpp 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXN 10000
#define MAXLEN 100

// 查找字符串是否存在
int findIndex(char arr[][MAXLEN], int size, char *target) {
    for (int i = 0; i < size; i++) {
        if (strcmp(arr[i], target) == 0) return i;
    }
    return -1;
}

// 全局变量(供 qsort 比较函数使用)
int countArr[MAXN];
int firstPosArr[MAXN];

// qsort 比较函数
// 排序规则:
// 1️ 次数降序
//  次数相同 → 首次出现位置升序
int cmp(const void *a, const void *b) {
    int i = *(int *)a;
    int j = *(int *)b;

    if (countArr[i] != countArr[j]) {
        return countArr[j] - countArr[i]; // 次数降序
    }
    return firstPosArr[i] - firstPosArr[j]; // 位置升序
}

int main() {
    char input[1000000];
    fgets(input, sizeof(input), stdin);

    // 去掉换行
    input[strcspn(input, "\n")] = 0;

    char *tokens[MAXN];
    int tokenCount = 0;

    // 使用 strtok 分割
    char *p = strtok(input, " ");
    while (p) {
        tokens[tokenCount++] = p;
        p = strtok(NULL, " ");
    }

    char unique[MAXN][MAXLEN];
    int size = 0;

    // 统计次数 + 首次位置
    for (int i = 0; i < tokenCount; i++) {
        int idx = findIndex(unique, size, tokens[i]);
        if (idx == -1) {
            strcpy(unique[size], tokens[i]);
            countArr[size] = 1;
            firstPosArr[size] = i;
            size++;
        } else {
            countArr[idx]++;
        }
    }

    // 收集答案索引
    int ansIdx[MAXN];
    int ansSize = 0;

    for (int i = 0; i < size; i++) {
        if (countArr[i] >= 3) {
            ansIdx[ansSize++] = i;
        }
    }

    // 使用 qsort 排序
    qsort(ansIdx, ansSize, sizeof(int), cmp);

    // 输出
    if (ansSize == 0) {
        printf("NONE");
        return 0;
    }

    for (int i = 0; i < ansSize; i++) {
        printf("%s", unique[ansIdx[i]]);
        if (i != ansSize - 1) printf(" ");
    }

    return 0;
}
相关推荐
无限码力4 天前
2026最新华为OD新系统机试解析 + 最新题库 + 备考策略
华为od·华为od机考·华为od机试真题·华为od机试·华为od新系统机试真题·2026华为od新系统机试题库·华为od机考题库
无限码力14 天前
华为OD机试真题 新系统 - API请求日志去重分析 (C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od上机考试真题·华为od机考真题·华为od4月15号机试真题·华为od新系统真题
无限码力18 天前
华为OD技术面真题 - Python开发 - 4
python·华为od·华为od技术面真题·华为od面试八股文·华为od面试真题·华为odpython开发真题·华为od技术面题目
无限码力20 天前
华为OD机试真题 新系统 - 直捣黄龙 (C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od上机考试真题·华为od机考真题·华为od新系统机试真题·华为od4月8号机试真题
无限码力22 天前
华为OD技术面真题 - JAVA开发- spring框架 - 7
java·开发语言·华为od·华为od面试真题·华为odjava八股文·华为odjava开发题目·华为odjava开发高频题目
无限码力1 个月前
华为OD机试双机位C卷真题-红黑图(C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od机试双机位c卷·华为od上机考试真题·华为od机考真题·华为od机试-红黑图·华为od机考真题-红黑图
无限码力1 个月前
华为OD机试双机位C卷-用户入网定期复评(C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od机试双机位c卷·华为od上机考试真题·华为od机考真题·华为od-用户入网定期复评
gis分享者1 个月前
华为OD面试-Java、C++、Pyhton等多语言实现-目录
java·c++·华为od·面试·目录·od·机试
无限码力1 个月前
华为OD机试双机位C卷-虚拟文件系统(C/C++/Py/Java/Js/Go)
华为od·华为od机试真题·华为od机试双机位c卷·华为od上机考试真题·华为od机考真题·华为od-虚拟文件系统·华为od机试题库