华为OD机试真题——告警抑制(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳实现

2025 A卷 100分 题型

本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享

华为OD机试真题《告警抑制》:


文章快捷目录

题目描述及说明

Java

python

JavaScript

C

GO

更多内容


题目名称:告警抑制


  1. 知识点:字符串处理、哈希映射(逻辑处理)
  2. 时间限制:1秒
  3. 空间限制:256MB
  4. 限定语言:不限

题目描述

告警抑制是指高优先级告警抑制低优先级告警的规则。高优先级告警产生后,低优先级告警不再产生。请根据原始告警列表和告警抑制关系,给出实际产生的告警列表。

输入描述

  1. 第一行为数字 N,表示告警抑制关系个数(0 ≤ N ≤ 120)。
  2. 接下来 N 行,每行由空格分隔的两个告警ID(格式:大写字母+0或1个数字),例如 A B,表示 A 抑制 B
  3. 最后一行为告警产生列表,列表长度范围为 [1,100],告警ID间以空格分隔。

输出描述

真实产生的告警列表(未被抑制的告警),按输入顺序输出,ID间以空格分隔。

示例

输入:

复制代码
2  
A B  
B C  
A B C D E  

输出:

复制代码
A D E  

解释

  • A 抑制 BB 抑制 C,因此 BC 被抑制,最终输出 A D E
补充规则
  1. 无循环抑制 :不会出现 A→B→A 的循环关系。
  2. 无传递抑制 :例如 A→B→C 时,A 不直接抑制 C,但被抑制的 B 仍可抑制 C
  3. 位置无关:被抑制的告警无论在高优先级告警的前后,均被屏蔽。

Java

问题分析

我们需要根据给定的告警抑制关系和原始告警列表,输出实际产生的未被抑制的告警列表。高优先级告警会抑制低优先级告警,无论它们在输入列表中的顺序如何。

解题思路

  1. 建立抑制关系映射:记录每个告警被哪些高优先级告警抑制。
  2. 快速判断抑制存在性:通过集合快速检查某个告警是否存在于输入列表中。
  3. 遍历原始告警列表:对于每个告警,检查是否存在抑制它的告警存在于输入列表中,若存在则过滤,否则保留。

代码实现

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

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int N = Integer.parseInt(scanner.nextLine()); // 读取抑制关系个数

        // 建立抑制关系映射表:key是被抑制的告警,value是抑制它的告警集合
        Map<String, Set<String>> suppressionMap = new HashMap<>();
        for (int i = 0; i < N; i++) {
            String[] parts = scanner.nextLine().split(" ");
            String suppressor = parts[0]; // 抑制者,例如A
            String suppressed = parts[1]; // 被抑制者,例如B
            if (!suppressionMap.containsKey(suppressed)) {
                suppressionMap.put(suppressed, new HashSet<>());
            }
            suppressionMap.get(suppressed).add(suppressor);
        }

        // 读取原始告警列表,并转换为集合用于快速查询
        String[] alerts = scanner.nextLine().split(" ");
        Set<String> inputSet = new HashSet<>(Arrays.asList(alerts));

        List<String> result = new ArrayList<>(); // 保存未被抑制的告警
        for (String alert : alerts) {
            boolean isSuppressed = false;
            // 检查当前告警是否有抑制者存在于输入列表中
            if (suppressionMap.containsKey(alert)) {
                for (String suppressor : suppressionMap.get(alert)) {
                    if (inputSet.contains(suppressor)) {
                        isSuppressed = true;
                        break;
                    }
                }
            }
            if (!isSuppressed) {
                result.add(alert); // 未被抑制,加入结果
            }
        }

        // 按输入顺序输出结果
        System.out.println(String.join(" ", result));
    }
}

代码详细解析

  1. 读取抑制关系个数 :使用 scanner.nextLine() 读取第一行并转换为整数 N
  2. 建立抑制关系映射
    • 使用 HashMap 存储,键为被抑制的告警,值为抑制它的告警集合。
    • 遍历 N 行,每行拆分为抑制者和被抑制者,将被抑制者作为键,抑制者添加到对应的集合。
  3. 读取原始告警列表 :拆分为数组并转换为集合 inputSet 用于快速查询。
  4. 过滤被抑制的告警
    • 遍历每个告警,检查是否存在抑制它的告警在 inputSet 中。
    • 若存在,则跳过;否则加入结果列表。
  5. 输出结果:按输入顺序拼接未被抑制的告警。

示例测试

示例1

输入:

复制代码
2
A B
B C
A B C D E

输出:

复制代码
A D E

解析:A 抑制 B,B 抑制 C,B 和 C 被过滤,D、E 无抑制。

示例2

输入:

复制代码
1
B A
B A

输出:

复制代码
B

解析:B 抑制 A,A 被过滤,B 被保留。

示例3

输入:

复制代码
0
A B C

输出:

复制代码
A B C

解析:无抑制关系,所有告警均保留。

综合分析

  1. 时间复杂度:O(N + M*K),其中 N 为抑制关系数,M 为告警列表长度,K 为每个告警的抑制者数量。高效处理最大数据规模。
  2. 空间复杂度:O(N + M),存储抑制关系和输入集合。
  3. 正确性:通过抑制关系映射和集合查询,确保所有抑制条件被正确判断。
  4. 适用性:处理所有合法输入,包括重复告警和不同顺序的抑制关系。

python

问题分析

我们需要根据给定的告警抑制关系和原始告警列表,输出实际产生的未被抑制的告警列表。高优先级告警会抑制低优先级告警,无论它们在输入列表中的顺序如何。


解题思路

  1. 建立抑制关系映射:记录每个告警被哪些高优先级告警抑制。
  2. 快速判断抑制存在性:通过集合快速检查某个告警是否存在于输入列表中。
  3. 遍历原始告警列表:对于每个告警,检查是否存在抑制它的告警存在于输入列表中,若存在则过滤,否则保留。

代码实现

python 复制代码
from collections import defaultdict

def main():
    n = int(input())  # 读取抑制关系个数
    suppression = defaultdict(set)  # 抑制关系映射表:被抑制的告警 → 抑制它的告警集合

    # 读取所有抑制关系
    for _ in range(n):
        suppressor, suppressed = input().strip().split()
        suppression[suppressed].add(suppressor)

    # 读取原始告警列表,并保留原始顺序
    alerts = input().strip().split()
    existing_alerts = set(alerts)  # 用于快速判断告警是否存在

    result = []
    for alert in alerts:
        # 检查当前告警是否被抑制
        is_suppressed = False
        # 如果当前告警存在于抑制关系中
        if alert in suppression:
            # 遍历所有能抑制它的告警,判断是否存在于原始列表
            for suppressor in suppression[alert]:
                if suppressor in existing_alerts:
                    is_suppressed = True
                    break  # 只要有一个抑制者存在即可跳过
        if not is_suppressed:
            result.append(alert)

    print(' '.join(result))

if __name__ == "__main__":
    main()

代码详细解析

  1. 读取输入

    • n:抑制关系数量。
    • suppression:使用 defaultdict(set) 存储抑制关系。例如 A B 表示 BA 抑制,存入 suppression['B'].add('A')
  2. 处理原始告警列表

    • alerts:保留原始顺序的告警列表。
    • existing_alerts:转换为集合用于快速查询。
  3. 过滤逻辑

    • 遍历每个告警 alert
    • 如果该告警在抑制关系中(suppression 字典中存在),检查其所有抑制者是否存在于 existing_alerts
    • 只要有一个抑制者存在,则当前告警被过滤。
  4. 输出结果:按原始顺序输出未被抑制的告警。


示例测试

示例1

输入:

复制代码
2
A B
B C
A B C D E

输出:

复制代码
A D E

解析:A 抑制 BB 抑制 CBC 被抑制。

示例2

输入:

复制代码
1
B A
B A

输出:

复制代码
B

解析:B 抑制 AA 被过滤。

示例3

输入:

复制代码
0
A B C

输出:

复制代码
A B C

解析:无抑制关系,所有告警保留。


综合分析

  1. 时间复杂度:O(N + M*K)

    • N 是抑制关系数量,M 是告警列表长度,K 是每个告警的最大抑制者数量。
    • 集合查询和遍历抑制者的时间复杂度为 O(1) 和 O(K),总体高效。
  2. 空间复杂度:O(N + M)

    • 存储抑制关系和原始告警列表。
  3. 正确性

    • 通过集合快速判断抑制者是否存在,确保所有抑制条件被正确检查。
  4. 适用性

    • 处理所有合法输入,包括重复告警和多级抑制关系。

JavaScript

问题分析

我们需要根据给定的告警抑制关系和原始告警列表,输出实际产生的未被抑制的告警列表。高优先级告警会抑制低优先级告警,无论它们在输入列表中的顺序如何。


解题思路

  1. 建立抑制关系映射:记录每个告警被哪些高优先级告警抑制。
  2. 快速判断抑制存在性:通过集合快速检查某个告警是否存在于输入列表中。
  3. 遍历原始告警列表:对于每个告警,检查是否存在抑制它的告警存在于输入列表中,若存在则过滤,否则保留。

代码实现

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

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

let n; // 抑制关系数量
let lineCount = 0;
const suppressionMap = {}; // 抑制关系表:{ 被抑制的告警: Set(抑制者) }
let originalAlerts; // 原始告警列表

rl.on('line', (line) => {
    if (lineCount === 0) { // 第一行读取N
        n = parseInt(line);
        lineCount++;
    } else if (lineCount <= n) { // 读取N行抑制关系
        const [suppressor, suppressed] = line.trim().split(' ');
        if (!suppressionMap[suppressed]) {
            suppressionMap[suppressed] = new Set();
        }
        suppressionMap[suppressed].add(suppressor);
        lineCount++;
    } else { // 最后一行读取原始告警列表
        originalAlerts = line.trim().split(' ');
        rl.close();
    }
});

rl.on('close', () => {
    const existingAlerts = new Set(originalAlerts); // 原始告警集合(快速查询)
    const result = [];
    for (const alert of originalAlerts) {
        let isSuppressed = false;
        if (suppressionMap[alert]) { // 检查当前告警是否被抑制
            // 遍历所有抑制者,判断是否存在于原始列表
            for (const suppressor of suppressionMap[alert]) {
                if (existingAlerts.has(suppressor)) {
                    isSuppressed = true;
                    break;
                }
            }
        }
        if (!isSuppressed) {
            result.push(alert); // 未被抑制,加入结果
        }
    }
    console.log(result.join(' '));
});

代码详细解析

  1. 输入处理

    • 使用 readline 逐行读取输入,第一行解析为抑制关系数量 n
    • 后续 n 行解析为抑制关系,存入 suppressionMap 对象,键为被抑制的告警,值为抑制者的集合。
    • 最后一行读取原始告警列表,转换为数组 originalAlerts
  2. 抑制关系映射

    javascript 复制代码
    if (!suppressionMap[suppressed]) {
        suppressionMap[suppressed] = new Set();
    }
    suppressionMap[suppressed].add(suppressor);
    • 若被抑制的告警不存在于映射表,初始化其对应的集合。
    • 将抑制者添加到被抑制告警的集合中。
  3. 过滤逻辑

    javascript 复制代码
    const existingAlerts = new Set(originalAlerts); // 快速查询集合
    for (const alert of originalAlerts) {
        if (suppressionMap[alert]) { // 当前告警可能被抑制
            for (const suppressor of suppressionMap[alert]) {
                if (existingAlerts.has(suppressor)) { // 抑制者存在
                    isSuppressed = true;
                    break;
                }
            }
        }
        if (!isSuppressed) result.push(alert);
    }
    • 遍历原始告警列表,检查每个告警是否被抑制。
    • 若存在抑制者存在于原始列表中,过滤该告警;否则保留。

示例测试

示例1

输入:

复制代码
2
A B
B C
A B C D E

输出:

复制代码
A D E

解析:A 抑制 B,B 抑制 C,B 和 C 被过滤。

示例2

输入:

复制代码
1
B A
B A

输出:

复制代码
B

解析:B 抑制 A,A 被过滤。

示例3

输入:

复制代码
0
A B C

输出:

复制代码
A B C

解析:无抑制关系,所有告警保留。


综合分析

  1. 时间复杂度:O(N + M*K)

    • N 是抑制关系数量,M 是告警列表长度,K 是每个告警的抑制者数量。
    • 集合查询时间为 O(1),遍历抑制关系的时间为 O(K)。
  2. 空间复杂度:O(N + M)

    • 存储抑制关系和原始告警列表。
  3. 正确性

    • 通过集合快速判断抑制者是否存在,确保所有抑制条件被正确过滤。
  4. 适用性

    • 处理所有合法输入,包括重复告警和多级抑制关系。

C++

问题分析

我们需要根据给定的告警抑制关系和原始告警列表,输出实际产生的未被抑制的告警列表。高优先级告警会抑制低优先级告警,无论它们在输入列表中的顺序如何。


解题思路

  1. 建立抑制关系映射:记录每个告警被哪些高优先级告警抑制。
  2. 快速判断抑制存在性:通过集合快速检查某个告警是否存在于输入列表中。
  3. 遍历原始告警列表:对于每个告警,检查是否存在抑制它的告警存在于输入列表中,若存在则过滤,否则保留。

代码实现

cpp 复制代码
#include <iostream>
#include <vector>
#include <string>
#include <sstream>
#include <unordered_map>
#include <unordered_set>

using namespace std;

int main() {
    // 读取抑制关系数量
    string line;
    getline(cin, line);
    int N = stoi(line);

    // 建立抑制关系映射表:key是被抑制的告警,value是抑制它的告警集合
    unordered_map<string, unordered_set<string>> suppressionMap;
    for (int i = 0; i < N; ++i) {
        getline(cin, line);
        istringstream iss(line);
        string suppressor, suppressed;
        iss >> suppressor >> suppressed;
        suppressionMap[suppressed].insert(suppressor);
    }

    // 读取原始告警列表并存入集合和数组
    getline(cin, line);
    istringstream iss_alerts(line);
    vector<string> alerts;
    unordered_set<string> alertSet;
    string alert;
    while (iss_alerts >> alert) {
        alerts.push_back(alert);
        alertSet.insert(alert);
    }

    // 过滤被抑制的告警
    vector<string> result;
    for (const string& a : alerts) {
        bool isSuppressed = false;
        if (suppressionMap.find(a) != suppressionMap.end()) {
            for (const string& suppressor : suppressionMap[a]) {
                if (alertSet.count(suppressor)) {
                    isSuppressed = true;
                    break;
                }
            }
        }
        if (!isSuppressed) {
            result.push_back(a);
        }
    }

    // 输出结果
    for (size_t i = 0; i < result.size(); ++i) {
        if (i > 0) cout << " ";
        cout << result[i];
    }
    cout << endl;

    return 0;
}

代码详细解析

  1. 读取抑制关系数量

    • 使用 getline 读取第一行并转换为整数 N
  2. 建立抑制关系映射

    • 使用 unordered_map 存储,键为被抑制的告警,值为抑制者的集合。
    • 逐行读取抑制关系,将被抑制的告警作为键,抑制者添加到对应的集合。
  3. 处理原始告警列表

    • 读取原始告警列表,存入 alerts 数组(保留顺序)和 alertSet 集合(快速查询)。
  4. 过滤逻辑

    • 遍历每个告警,检查是否存在抑制者存在于 alertSet 中。
    • 若存在,则跳过;否则保留该告警。
  5. 输出结果

    • 按原始顺序输出未被抑制的告警,用空格分隔。

示例测试

示例1

输入:

复制代码
2
A B
B C
A B C D E

输出:

复制代码
A D E

解析:A 抑制 B,B 抑制 C,B 和 C 被过滤。

示例2

输入:

复制代码
1
B A
B A

输出:

复制代码
B

解析:B 抑制 A,A 被过滤。

示例3

输入:

复制代码
0
A B C

输出:

复制代码
A B C

解析:无抑制关系,所有告警保留。


综合分析

  1. 时间复杂度:O(N + M*K)

    • N 是抑制关系数量,M 是告警列表长度,K 是每个告警的抑制者数量。
    • 集合查询时间为 O(1),遍历抑制关系的时间为 O(K)。
  2. 空间复杂度:O(N + M)

    • 存储抑制关系和原始告警列表。
  3. 正确性

    • 通过集合快速判断抑制者是否存在,确保所有抑制条件被正确检查。
  4. 适用性

    • 处理所有合法输入,包括重复告警和多级抑制关系。

C

问题分析

我们需要根据给定的告警抑制关系和原始告警列表,输出实际产生的未被抑制的告警列表。高优先级告警会抑制低优先级告警,无论它们在输入列表中的顺序如何。关键在于高效存储抑制关系并快速判断告警是否被抑制。


解题思路

  1. 输入处理:读取抑制关系并构建数据结构,保存每个告警的抑制者列表。
  2. 原始告警存储:将原始告警保存到数组以便按顺序输出,同时支持快速存在性检查。
  3. 过滤逻辑:遍历每个告警,检查其是否被列表中的任一抑制者抑制。
  4. 输出结果:按顺序输出未被抑制的告警。

代码实现

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

// 抑制者链表节点
typedef struct SuppressorNode {
    char suppressor[32];
    struct SuppressorNode *next;
} SuppressorNode;

// 抑制关系条目:被抑制的告警及其抑制者链表
typedef struct {
    char suppressed[32];
    SuppressorNode *sup_list;
} SuppressionEntry;

SuppressionEntry suppression_entries[120]; // 最大抑制关系数
int num_suppression_entries = 0;

// 判断字符串是否存在于原始告警列表中
bool is_exist(char *str, char **alerts, int alert_count) {
    for (int i = 0; i < alert_count; i++) {
        if (strcmp(str, alerts[i]) == 0) {
            return true;
        }
    }
    return false;
}

int main() {
    int N;
    char line[1024];
    
    // 读取抑制关系数量
    fgets(line, sizeof(line), stdin);
    sscanf(line, "%d", &N);
    
    // 读取抑制关系并构建数据结构
    for (int i = 0; i < N; i++) {
        fgets(line, sizeof(line), stdin);
        char suppressor[32], suppressed[32];
        sscanf(line, "%s %s", suppressor, suppressed);
        
        // 查找是否已有对应的被抑制条目
        bool found = false;
        for (int j = 0; j < num_suppression_entries; j++) {
            if (strcmp(suppression_entries[j].suppressed, suppressed) == 0) {
                // 添加抑制者到链表头部
                SuppressorNode *node = (SuppressorNode *)malloc(sizeof(SuppressorNode));
                strcpy(node->suppressor, suppressor);
                node->next = suppression_entries[j].sup_list;
                suppression_entries[j].sup_list = node;
                found = true;
                break;
            }
        }
        if (!found) {
            // 新增条目
            strcpy(suppression_entries[num_suppression_entries].suppressed, suppressed);
            SuppressorNode *node = (SuppressorNode *)malloc(sizeof(SuppressorNode));
            strcpy(node->suppressor, suppressor);
            node->next = NULL;
            suppression_entries[num_suppression_entries].sup_list = node;
            num_suppression_entries++;
        }
    }
    
    // 读取原始告警列表
    fgets(line, sizeof(line), stdin);
    char *alerts[100];
    int alert_count = 0;
    char *token = strtok(line, " \n");
    while (token != NULL && alert_count < 100) {
        alerts[alert_count] = strdup(token); // 复制字符串
        alert_count++;
        token = strtok(NULL, " \n");
    }
    
    // 过滤被抑制的告警
    char *result[100];
    int result_count = 0;
    for (int i = 0; i < alert_count; i++) {
        char *current = alerts[i];
        bool is_suppressed = false;
        
        // 检查当前告警是否被抑制
        for (int j = 0; j < num_suppression_entries; j++) {
            if (strcmp(suppression_entries[j].suppressed, current) == 0) {
                // 遍历抑制者链表,判断是否存在
                SuppressorNode *node = suppression_entries[j].sup_list;
                while (node != NULL) {
                    if (is_exist(node->suppressor, alerts, alert_count)) {
                        is_suppressed = true;
                        break;
                    }
                    node = node->next;
                }
                if (is_suppressed) break;
            }
        }
        if (!is_suppressed) {
            result[result_count++] = current;
        }
    }
    
    // 输出结果
    for (int i = 0; i < result_count; i++) {
        if (i > 0) printf(" ");
        printf("%s", result[i]);
    }
    printf("\n");
    
    // 释放内存
    for (int i = 0; i < alert_count; i++) {
        free(alerts[i]);
    }
    for (int i = 0; i < num_suppression_entries; i++) {
        SuppressorNode *node = suppression_entries[i].sup_list;
        while (node != NULL) {
            SuppressorNode *temp = node;
            node = node->next;
            free(temp);
        }
    }
    return 0;
}

代码详细解析

  1. 数据结构定义

    • SuppressorNode:链表节点,存储抑制者ID。
    • SuppressionEntry:被抑制的告警及其抑制者链表。
  2. 读取抑制关系

    • 每行拆分为抑制者和被抑制者。
    • 若被抑制的告警已存在,将抑制者添加到链表头部;否则创建新条目。
  3. 原始告警处理

    • 使用strtok分割输入行,保存到alerts数组,并复制字符串(strdup)。
  4. 过滤被抑制告警

    • 遍历每个告警,检查其是否在抑制关系中。
    • 若存在抑制关系,遍历抑制者链表,判断是否存在原始列表中。
  5. 输出结果

    • 按顺序输出未被抑制的告警。
  6. 内存释放

    • 释放动态分配的告警字符串和抑制者链表节点。

示例测试

示例1

输入:

复制代码
2
A B
B C
A B C D E

输出:

复制代码
A D E

解析:A抑制B,B抑制C,B和C被过滤。

示例2

输入:

复制代码
1
B A
B A

输出:

复制代码
B

解析:B抑制A,A被过滤。

示例3

输入:

复制代码
0
A B C

输出:

复制代码
A B C

解析:无抑制关系,所有告警保留。


综合分析

  1. 时间复杂度

    • 读取抑制关系:O(N),N为抑制关系数。
    • 过滤告警:O(M*K),M为告警列表长度,K为抑制者数量。
    • 总体时间复杂度为O(N + M*K),适用于题目限制。
  2. 空间复杂度

    • 存储抑制关系和原始告警列表,空间复杂度为O(N + M)。
  3. 正确性

    • 通过链表和线性查找确保所有抑制关系被正确处理。
  4. 适用性

    • 处理所有合法输入,包括循环抑制和传递抑制(但题目规定不存在)。

GO

问题分析

我们需要根据告警抑制关系和原始告警列表,过滤掉所有被抑制的告警,输出未被抑制的告警。高优先级告警会抑制所有直接关联的低优先级告警,无论其顺序如何。关键在于快速判断某个告警是否被其他告警抑制。


解题思路

  1. 存储抑制关系:使用嵌套字典记录每个告警的抑制者集合。
  2. 快速存在性检查:将原始告警存入集合,以便快速判断抑制者是否存在。
  3. 遍历过滤:对于每个告警,检查其是否有抑制者存在于原始列表中,若存在则过滤。

代码实现

go 复制代码
package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	// 读取抑制关系数量
	scanner.Scan()
	var n int
	fmt.Sscanf(scanner.Text(), "%d", &n)

	// 初始化抑制关系映射:被抑制告警 → 抑制者集合
	suppression := make(map[string]map[string]struct{})

	// 读取并存储抑制关系
	for i := 0; i < n; i++ {
		scanner.Scan()
		parts := strings.Split(scanner.Text(), " ")
		if len(parts) != 2 {
			continue // 跳过格式错误行
		}
		suppressor, suppressed := parts[0], parts[1]
		if _, ok := suppression[suppressed]; !ok {
			suppression[suppressed] = make(map[string]struct{})
		}
		suppression[suppressed][suppressor] = struct{}{}
	}

	// 读取原始告警列表并构建存在集合
	scanner.Scan()
	alerts := strings.Fields(scanner.Text())
	existing := make(map[string]struct{})
	for _, a := range alerts {
		existing[a] = struct{}{}
	}

	// 过滤被抑制的告警
	var result []string
	for _, a := range alerts {
		suppressed := false
		// 检查当前告警是否有抑制者在原始列表中
		if suppressors, ok := suppression[a]; ok {
			for s := range suppressors {
				if _, exists := existing[s]; exists {
					suppressed = true
					break
				}
			}
		}
		if !suppressed {
			result = append(result, a)
		}
	}

	// 输出结果
	fmt.Println(strings.Join(result, " "))
}

代码详细解析

  1. 读取抑制关系数量

    • 使用 bufio.Scanner 读取输入的第一行,解析为整数 n
  2. 存储抑制关系

    • 使用嵌套字典 suppression,外层键为被抑制告警,内层键为抑制者集合。
    • 每行抑制关系拆分为抑制者(suppressor)和被抑制者(suppressed),存入字典。
  3. 处理原始告警列表

    • 将原始告警存入切片 alerts 以保留顺序。
    • 使用字典 existing 存储所有原始告警,以便 O(1) 时间存在性检查。
  4. 过滤逻辑

    • 遍历每个原始告警 a
    • a 存在于 suppression 中,遍历其所有抑制者,检查是否存在于 existing
    • 若存在任一抑制者,则 a 被抑制,否则保留。
  5. 输出结果

    • 使用 strings.Join 按原始顺序拼接未被抑制的告警。

示例测试

示例1

输入:

复制代码
2
A B
B C
A B C D E

输出:

复制代码
A D E

解析:A 抑制 B,B 抑制 C。B 和 C 被过滤。

示例2

输入:

复制代码
1
B A
B A

输出:

复制代码
B

解析:B 抑制 A,A 被过滤。

示例3

输入:

复制代码
0
A B C

输出:

复制代码
A B C

解析:无抑制关系,全部保留。


综合分析

  1. 时间复杂度

    • 读取输入:O(N + M),N 为抑制关系数,M 为原始告警数。
    • 过滤过程:O(M*K),K 为每个告警的抑制者数量。每个告警的抑制者检查为 O(1)。
  2. 空间复杂度

    • 抑制关系存储:O(N),每个抑制关系存储一次。
    • 原始告警存储:O(M),存储列表和集合。
  3. 正确性

    • 通过直接检查抑制者是否存在于原始列表,确保所有抑制关系被正确处理。
  4. 适用性

    • 处理大规模数据高效,适用于题目给出的最大输入限制。

更多内容:

https://www.kdocs.cn/l/cvk0eoGYucWA

本文发表于【纪元A梦】,关注我,获取更多实用教程/资源!

相关推荐
海码0071 小时前
【Hot 100】 146. LRU 缓存
数据结构·c++·算法·链表·缓存·hot100
今天也是元气满满的一天呢1 小时前
java学习之数据结构:一、数组
java·数据结构·学习
工藤新一¹1 小时前
C++/SDL 进阶游戏开发 —— 双人塔防(代号:村庄保卫战 20)
c++·单例模式·游戏引擎·sdl·c++游戏开发
买了一束花2 小时前
二、机器学习中Python变量基础
开发语言·python·机器学习·conda
heyCHEEMS2 小时前
最大子段和 Java
java·开发语言·算法
Gui林2 小时前
ros2 humble 控制真实机械臂(以lerobot为例)
linux·python
-曾牛2 小时前
探索 Spring AI 的 ChatClient API:构建智能对话应用的利器
java·人工智能·spring boot·后端·spring·springai·ai指南
白露与泡影2 小时前
使用OAuth2保护Spring AI MCP服务!
java·后端·spring
我是一只鱼02232 小时前
LeetCode算法题 (设计链表)Day16!!!C/C++
数据结构·c++·算法·leetcode·链表
magic 2452 小时前
Spring 命名空间注入:p、c 与 .util 的深度解析
java·前端·spring