目录

题目

思路

Code


题目

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

思路

比较简单的排序算法题目,用一次遍历统计两个信息:

  1. 每个日志标识出现了多少次
  2. 每个日志标识第一次出现的位置

然后把所有出现次数大于等于 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。让他帮助你查询原因。

更多推荐