华为OD机试(E卷+D卷+C卷)最新题库【超值优惠】Java/Python/C++合集
考勤记录是分析和考核职工工作时间利用情况的原始依据,也是计算职工工资的原始依据,为了正确地计算职工工资和监督工资基金使用情况,公司决定对员工的手机打卡记录进行异常排查。
如果出现以下两种情况,则认为打卡异常:
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
补充说明
输入:
2
100000,10,1,ABCD,ABCD
100000,50,10,ABCD,ABCD
输出:
100000,10,1,ABCD,ABCD;100000,50,10,ABCD,ABCD
说明:
第一条记录是异常的,因为第二条记录与它的间隔不超过60分钟但是打卡距离超过了5km,同理第二条记录也是异常的。
输入:
2
100000,10,1,ABCD,ABCD
100000,80,10,ABCE,ABCD
输出:
100000,80,10,ABCE,ABCD
说明:
第二条记录的注册设备号与打卡设备号不一致,所以是异常记录
输入:
2
100000,10,1,ABCD,ABCD
100001,80,10,ABCE,ABCE
输出:
null
说明:
无异常打卡记录,所以返回null
#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;
}
题目分析
题目要求判断并输出异常的考勤记录,异常的标准如下:
- 实际设备号和注册设备号不一致。
- 同一员工的两次打卡记录时间差小于 60 分钟,并且打卡地点差距超过 5 公里。
根据题意,题目可以视为遍历记录并进行条件判断的题目。我们需要对每条记录进行检查,符合异常条件的则输出。
解题思路
- 结构体定义:
- 我们需要使用一个
Record
结构体来存储每一条打卡记录的信息(工号、时间、打卡距离、实际设备号、注册设备号)。- 数据解析:
- 通过逗号分隔的字符串,我们可以使用
getline()
函数解析每一行数据,填充到Record
结构体中。- 异常判断:
- 设备号检查:直接检查
actualDeviceNumber
是否与registeredDeviceNumber
不一致。- 时间和打卡距离检查:遍历其他记录,检查同一员工的记录,计算时间差和距离差。若时间差小于 60 分钟并且距离差大于 5 公里,则认为是异常记录。
- 输出格式:
- 使用
ostringstream
来拼接异常记录,多个异常记录之间用分号;
分隔。若没有异常记录,输出"null"
。
整理题解不易, 如果有帮助到您,请给点个赞 ❤️ 和收藏 ⭐,让更多的人看到。