华为OD机试真题:异常的打卡记录(E卷、C++)

华为OD机试(E卷+D卷+C卷)最新题库【超值优惠】Java/Python/C++合集

华为OD机试真题:异常的打卡记录(E卷、C++)_第1张图片

题目描述

考勤记录是分析和考核职工工作时间利用情况的原始依据,也是计算职工工资的原始依据,为了正确地计算职工工资和监督工资基金使用情况,公司决定对员工的手机打卡记录进行异常排查。

如果出现以下两种情况,则认为打卡异常:
1、实际设备号与注册设备号不一样;

2、或者,同一个员工的两个打卡记录的时间小于60分钟并且打卡距离超过5km。

给定打卡记录的字符串数组clockRecords(每个打卡记录组成为:工号:时间(分钟):打卡距离(km):实际设备号;注册设备号),返回其中异常的打卡记录(按输入顺序输出)。

输入描述

第一行输入为N,表示打卡记录数;
之后的N行为打卡记录,每一行为一条打卡记录。
例如:
2
100000,10,1,ABCD,ABCD
100000,50,10,ABCD,ABCD

输出描述

输出为异常的打卡记录,例如:100000,10,1,ABCD,ABCD;100000,50,10,ABCD,ABCD

补充说明

  1. clockRecords长度<=1000;
  2. clockRecords[i]格式:{id},(time},{distance},{actualDeviceNumber},{registeredDeviceNumber}
  3. id由6位数字组成;
  4. time由整数组成,范围为0~1000;
  5. distance由整数组成,范围为0~100;
  6. actualDeviceNumber与registeredDeviceNumber由四位大写字母组成。

示例1

输入:
2
100000,10,1,ABCD,ABCD
100000,50,10,ABCD,ABCD

输出:
100000,10,1,ABCD,ABCD;100000,50,10,ABCD,ABCD

说明:
第一条记录是异常的,因为第二条记录与它的间隔不超过60分钟但是打卡距离超过了5km,同理第二条记录也是异常的。

示例2

输入:
2
100000,10,1,ABCD,ABCD
100000,80,10,ABCE,ABCD

输出:
100000,80,10,ABCE,ABCD

说明:
第二条记录的注册设备号与打卡设备号不一致,所以是异常记录

示例3

输入:
2
100000,10,1,ABCD,ABCD
100001,80,10,ABCE,ABCE

输出:
null

说明:
无异常打卡记录,所以返回null

C++

#include 

using namespace std;

typedef struct Record {
    int id{};  // 工号
    int timestamp{}; // 时间
    int locationDistance{}; // 打卡距离
    string actualDeviceNumber; // 实际设备号
    string registeredDeviceNumber; // 注册设备号

    // 定义结构体的打印格式
    friend ostream &operator<<(ostream &os, const Record &record) {
        os << record.id << "," << record.timestamp
           << "," << record.locationDistance
           << "," << record.actualDeviceNumber
           << "," << record.registeredDeviceNumber;
        return os;
    }
};

// 解析一行数据到Record结构体
Record parseRecord(const string &line) {
    Record record;
    istringstream ss(line);
    string token;

    getline(ss, token, ',');
    record.id = stoi(token);

    getline(ss, token, ',');
    record.timestamp = stoi(token);

    getline(ss, token, ',');
    record.locationDistance = stoi(token);

    getline(ss, record.actualDeviceNumber, ',');
    getline(ss, record.registeredDeviceNumber, ',');
    return record;
}

// 判断记录是否异常
bool isException(const Record &record, const vector<Record> &records) {
    // 设备号不一致
    if (record.registeredDeviceNumber != record.actualDeviceNumber) return true;

    return any_of(records.begin(), records.end(), [&record](const auto &other) {
        return record.id == other.id && // 同一个员工
               abs(record.timestamp - other.timestamp) < 60 &&  // 打卡记录的时间小于60分钟
               abs(record.locationDistance - other.locationDistance) > 5;  // 打卡距离超过5km
    });
}

int main() {
    int n;
    cin >> n;
    cin.ignore(); // 忽略换行符

    vector<Record> records(n);
    for (int i = 0; i < n; i++) {
        string line;
        getline(cin, line);
        records[i] = parseRecord(line);
    }

    // 使用ostringstream来优化输出格式
    ostringstream output;
    bool hasException = false;
    for (const auto &record : records) {
        if (isException(record, records)) {
            if (hasException) output << ';'; // 多个异常记录间用;分隔
            output << record;
            hasException = true;
        }
    }

    // 如果没有异常,输出 "null"
    if (!hasException) {
        output << "null";
    }

    cout << output.str() << endl;

    return 0;
}

题目分析

题目要求判断并输出异常的考勤记录,异常的标准如下:

  1. 实际设备号和注册设备号不一致。
  2. 同一员工的两次打卡记录时间差小于 60 分钟,并且打卡地点差距超过 5 公里。

根据题意,题目可以视为遍历记录并进行条件判断的题目。我们需要对每条记录进行检查,符合异常条件的则输出。

解题思路

  1. 结构体定义
    • 我们需要使用一个 Record 结构体来存储每一条打卡记录的信息(工号、时间、打卡距离、实际设备号、注册设备号)。
  2. 数据解析
    • 通过逗号分隔的字符串,我们可以使用 getline() 函数解析每一行数据,填充到 Record 结构体中。
  3. 异常判断
    • 设备号检查:直接检查 actualDeviceNumber 是否与 registeredDeviceNumber 不一致。
    • 时间和打卡距离检查:遍历其他记录,检查同一员工的记录,计算时间差和距离差。若时间差小于 60 分钟并且距离差大于 5 公里,则认为是异常记录。
  4. 输出格式
    • 使用 ostringstream 来拼接异常记录,多个异常记录之间用分号 ; 分隔。若没有异常记录,输出 "null"

整理题解不易, 如果有帮助到您,请给点个赞 ‍❤️‍ 和收藏 ⭐,让更多的人看到。

你可能感兴趣的:(华为od,c++,开发语言,面试,机试,算法)