华为OD机试 - 垃圾短信识别(Python/JS/C/C++ 2024 E卷 100分)

在这里插入图片描述

华为OD机试 2024E卷题库疯狂收录中,刷题点这里

专栏导读

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

一、题目描述

大⼤⼯对垃圾短信深恶痛绝,希望能够对垃圾短信发件者进⾏识别,为此,很多软件增加了垃圾短信的识别机制。经过分析,发现正常⽤⼾的短信通常具备交互性⽽垃圾短信往往都是⼤量单向的短信,按照如下规则进⾏垃圾短信识别:

本题中,发送者A符合以下条件之⼀的,则认为A是垃圾短信发送者:

A发送给B的直接短信中,没有发送给B的总数>5;
A发送的短信数>A接收的短信数 M>10;
如果M存在,A发送给C的短信数-A接收到C的短信数 N>5;

二、输入描述

第⼀⾏是条⽬总数,接下来是⼏⾏具体的条⽬,每个条⽬是⼀对ID,第⼀个数字是发送者ID,后⾯的数字是接收者ID,中间空格隔开,所有的ID都为⽆符号整数,ID最⼤值为100;

同⼀条⽬中,两个ID不会相同(即不会把⼀个⼈发消息⾃⼰)。

最后⼀⾏为指定的ID。

三、输出描述

输出该ID是否为垃圾短信发送者,并且按垃圾序列输出L与M的值(由于N值不唯⼀,不需要输出);输出均为空格分隔。

四、测试用例

1、输入

15
1 2
1 3
1 4
1 5
1 6
1 7
1 8
1 9
1 10
1 11
1 12
1 13
1 14
14 1
1 15
1

2、输出

true 13 13

3、说明

true 表示1是垃圾短信发送者,两个数字,代表发送者1对应的L和M值。
true 13 13 中间以一个空格分割。注意 true 是字符串输出。

五、解题思路

  1. 使用Scanner读取输入,包括短信记录的数量、具体记录、以及要检查的指定ID。
  2. 统计发送和接收信息:
    • 使用LinkedList存储发送和接收的ID。
    • 使用HashMap统计每个ID发送和接收的短信数量。
  3. 计算L值和M值:
    • L值:发送者发送给不同接收者的短信数量(不重复计算接收者)。
    • M值:发送者发送的短信数量减去接收的短信数量。
  4. 判断垃圾短信发送者:
    • 检查以下条件:
      • L值大于5。
      • M值大于10。
      • 对于每个发送给的接收者,检查发送数量与接收数量的差值是否大于5。
  5. 输出结果:打印结果,格式为true/false L M。

六、Python算法源码

# 导入所需的模块
from collections import defaultdict

def get_result(tid, arr):
    # 用于存储发送和接收的ID
    send = []
    receive = []
    
    # 统计发送和接收的数量
    send_count = defaultdict(int)  # 发送统计
    receive_count = defaultdict(int)  # 接收统计

    # 处理每条短信记录
    for sid, rid in arr:
        # 如果发送者是指定的ID
        if sid == tid:
            send.append(rid)  # 添加接收者ID到发送列表
            send_count[rid] += 1  # 统计发送给接收者的次数

        # 如果接收者是指定的ID
        if rid == tid:
            receive.append(sid)  # 添加发送者ID到接收列表
            receive_count[sid] += 1  # 统计接收到的次数

    # 使用集合去重
    send_set = set(send)
    receive_set = set(receive)

    # 计算连接的数量(即同时发送和接收的ID)
    connect = send_set.intersection(receive_set)

    # 计算L和M值
    l = len(send_set) - len(connect)  # L值
    m = len(send) - len(receive)  # M值

    # 判断是否为垃圾短信发送者
    is_spammers = l > 5 or m > 10

    # 如果不是垃圾发送者,检查其他条件
    if not is_spammers:
        for rid in send_set:
            # 检查发送给每个接收者的差值是否大于5
            if send_count[rid] - receive_count[rid] > 5:
                is_spammers = True
                break

    # 返回结果
    return f"{is_spammers} {l} {m}"

# 主程序入口
if __name__ == "__main__":
    # 读取条目总数
    n = int(input())
    arr = []

    # 读取每条短信记录
    for _ in range(n):
        arr.append(tuple(map(int, input().split())))

    # 读取指定的ID
    id = int(input())

    # 调用计算结果的方法并输出
    print(get_result(id, arr))

七、JavaScript算法源码

function getResult(tid, arr) {
    // 用于存储发送和接收的ID
    const send = [];
    const receive = [];
    
    // 统计发送和接收的数量
    const sendCount = new Map();  // 发送统计
    const receiveCount = new Map();  // 接收统计

    // 处理每条短信记录
    for (let [sid, rid] of arr) {
        // 如果发送者是指定的ID
        if (sid === tid) {
            send.push(rid);  // 添加接收者ID到发送列表
            sendCount.set(rid, (sendCount.get(rid) || 0) + 1);  // 统计发送给接收者的次数
        }

        // 如果接收者是指定的ID
        if (rid === tid) {
            receive.push(sid);  // 添加发送者ID到接收列表
            receiveCount.set(sid, (receiveCount.get(sid) || 0) + 1);  // 统计接收到的次数
        }
    }

    // 使用Set去重
    const sendSet = new Set(send);
    const receiveSet = new Set(receive);

    // 计算连接的数量(即同时发送和接收的ID)
    const connect = [...sendSet].filter(id => receiveSet.has(id));

    // 计算L和M值
    const l = sendSet.size - connect.length;  // L值
    const m = send.length - receive.length;  // M值

    // 判断是否为垃圾短信发送者
    let isSpammers = l > 5 || m > 10;

    // 如果不是垃圾发送者,检查其他条件
    if (!isSpammers) {
        for (let rid of sendSet) {
            // 检查发送给每个接收者的差值是否大于5
            if ((sendCount.get(rid) || 0) - (receiveCount.get(rid) || 0) > 5) {
                isSpammers = true;
                break;
            }
        }
    }

    // 返回结果
    return `${isSpammers} ${l} ${m}`;
}

// 主程序入口
const input = require('fs').readFileSync('/dev/stdin', 'utf-8').trim().split('\n');
const n = parseInt(input[0]);
const arr = input.slice(1, n + 1).map(line => line.split(' ').map(Number));
const id = parseInt(input[n + 1]);

// 调用计算结果的方法并输出
console.log(getResult(id, arr));

八、C算法源码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_USERS 100

// 统计发送和接收的数量
int sendCount[MAX_USERS + 1];
int receiveCount[MAX_USERS + 1];

int getResult(int tid, int arr[][2], int n) {
    // 用于存储发送和接收的唯一ID
    int sendSet[MAX_USERS + 1] = {0}; // 发送的接收者ID
    int receiveSet[MAX_USERS + 1] = {0}; // 接收的发送者ID
    int sendSize = 0, receiveSize = 0;

    // 处理每条短信记录
    for (int i = 0; i < n; i++) {
        int sid = arr[i][0]; // 发送者ID
        int rid = arr[i][1]; // 接收者ID

        // 如果发送者是指定的ID
        if (sid == tid) {
            sendSet[rid] = 1; // 标记该接收者ID
            sendCount[rid]++; // 统计发送给接收者的次数
            sendSize++; // 增加发送数量
        }

        // 如果接收者是指定的ID
        if (rid == tid) {
            receiveSet[sid] = 1; // 标记该发送者ID
            receiveCount[sid]++; // 统计接收到的次数
            receiveSize++; // 增加接收数量
        }
    }

    // 计算连接的数量(即同时发送和接收的ID)
    int connect = 0;
    for (int i = 1; i <= MAX_USERS; i++) {
        if (sendSet[i] && receiveSet[i]) {
            connect++; // 计算同时发送和接收的数量
        }
    }

    // 计算L和M值
    int l = sendSize - connect; // L值
    int m = 0;
    for (int i = 1; i <= MAX_USERS; i++) {
        m += sendCount[i]; // 发送的总数
    }
    m -= receiveSize; // M值

    // 判断是否为垃圾短信发送者
    int isSpammers = (l > 5 || m > 10);

    // 如果不是垃圾发送者,检查其他条件
    if (!isSpammers) {
        for (int i = 1; i <= MAX_USERS; i++) {
            if (sendSet[i] && (sendCount[i] - receiveCount[i] > 5)) {
                isSpammers = 1; // 标记为垃圾短信发送者
                break;
            }
        }
    }

    // 输出结果
    printf("%s %d %d\n", isSpammers ? "true" : "false", l, m);
    return 0;
}

// 主程序入口
int main() {
    int n;
    scanf("%d", &n);
    int arr[n][2];

    // 读取每条短信记录
    for (int i = 0; i < n; i++) {
        scanf("%d %d", &arr[i][0], &arr[i][1]);
    }

    // 读取指定的ID
    int id;
    scanf("%d", &id);

    // 调用计算结果的方法
    getResult(id, arr, n);
    return 0;
}

九、C++算法源码

#include <iostream>
#include <vector>
#include <unordered_map>
#include <unordered_set>

using namespace std;

// 计算结果的函数
string getResult(int tid, const vector<pair<int, int>>& arr) {
    unordered_set<int> sendSet;  // 用于存储发送的接收者ID
    unordered_set<int> receiveSet;  // 用于存储接收的发送者ID
    unordered_map<int, int> sendCount;  // 统计发送给每个接收者的次数
    unordered_map<int, int> receiveCount;  // 统计接收到的次数

    // 处理每条短信记录
    for (const auto& ele : arr) {
        int sid = ele.first;  // 发送者ID
        int rid = ele.second;  // 接收者ID

        // 如果发送者是指定的ID
        if (sid == tid) {
            sendSet.insert(rid);  // 添加接收者ID到发送集合
            sendCount[rid]++;  // 统计发送给接收者的次数
        }

        // 如果接收者是指定的ID
        if (rid == tid) {
            receiveSet.insert(sid);  // 添加发送者ID到接收集合
            receiveCount[sid]++;  // 统计接收到的次数
        }
    }

    // 计算连接的数量(即同时发送和接收的ID)
    int connect = 0;
    for (int id : sendSet) {
        if (receiveSet.count(id)) {
            connect++;  // 统计同时发送和接收的ID
        }
    }

    // 计算L和M值
    int l = sendSet.size() - connect;  // L值
    int m = sendCount.size() - receiveSet.size();  // M值

    // 判断是否为垃圾短信发送者
    bool isSpammers = (l > 5 || m > 10);

    // 如果不是垃圾发送者,检查其他条件
    if (!isSpammers) {
        for (int id : sendSet) {
            if (sendCount[id] - receiveCount[id] > 5) {
                isSpammers = true;  // 标记为垃圾短信发送者
                break;
            }
        }
    }

    // 返回结果
    return to_string(isSpammers) + " " + to_string(l) + " " + to_string(m);
}

// 主程序入口
int main() {
    int n;
    cin >> n;  // 读取条目总数
    vector<pair<int, int>> arr(n);

    // 读取每条短信记录
    for (int i = 0; i < n; i++) {
        cin >> arr[i].first >> arr[i].second;  // 读取发送者和接收者ID
    }

    // 读取指定的ID
    int id;
    cin >> id;

    // 调用计算结果的方法并输出
    cout << getResult(id, arr) << endl;
    return 0;
}


🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2024 E卷 200分)

🏆本文收录于,华为OD机试真题(Python/JS/C/C++)

刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

华为OD机试-2023真题的考点主要为以下几个类: 1. 数据结构与算法:考察对各种常用数据结构(如数组、链表、栈、队列、树、图等)和算法(如排序、查找、递归、动态规划等)的理解和应用能力,以及对时间复杂度和空间复杂度的析和优化。 2. 编程语言和语法:考察对编程语言(如C++Python等)的基本语法和特性的掌握程度,包括变量、运算符、控制流程、函数、类等。同时还要求考生熟练运用相关的标准库和常用的数据结构和算法。 3. 网络与操作系统:考察对计算机网络和操作系统的基本原理和常用技术的了解,包括网络通信、TCP/IP协议、进程管理、内存管理、文件系统等。要求考生理解并能解决相关的问题。 4. 数据库与SQL:考察对数据库的基本概念和原理的理解,包括数据模型、关系代数、SQL语言等内容。要求考生能够编写和优化SQL查询语句,处理常见的数据库操作和性能问题。 5. 系统设计与架构:考察对大型系统的设计和架构的理解,包括系统需求析、模块划、接口设计等。要求考生能够根据需求或场景提出可行的系统设计方案,并能解决相关的实际问题。 总体来说,华为OD机试-2023真题的考点比较全面,涵盖了计算机科学与技术的多个方面。考生需要具备扎实的数据结构与算法基础,熟悉常用编程语言和标准库的使用,了解网络和操作系统的基本原理,掌握数据库和SQL语言的基本知识,同时具备系统设计和架构的能力。只有在这些方面的基础上才能够应对各种考题,并取得优异的表现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值